日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

fsx 簡介:適用于 JavaScript 的現(xiàn)代文件系統(tǒng) API

來源: 責(zé)編: 時(shí)間:2024-01-23 17:23:02 220觀看
導(dǎo)讀JavaScript 運(yùn)行時(shí)中的文件系統(tǒng) API 已經(jīng)很久沒有這么好了,這是我試圖做出一個(gè)更好的文件系統(tǒng) API 的嘗試。我們今天擁有的 JavaScript API 比十年前要好得多。考慮一下從 XMLHttpRequest 到 fetch()的轉(zhuǎn)變:開發(fā)者體驗(yàn)

JavaScript 運(yùn)行時(shí)中的文件系統(tǒng) API 已經(jīng)很久沒有這么好了,這是我試圖做出一個(gè)更好的文件系統(tǒng) API 的嘗試。kMh28資訊網(wǎng)——每日最新資訊28at.com

kMh28資訊網(wǎng)——每日最新資訊28at.com

我們今天擁有的 JavaScript API 比十年前要好得多。考慮一下從 XMLHttpRequest 到 fetch()的轉(zhuǎn)變:開發(fā)者體驗(yàn)顯著改善,允許我們編寫更簡潔、功能性更強(qiáng)的代碼來完成同樣的事情。異步編程的 promises 的引入允許了這種變化,以及一系列其他變化,使得 JavaScript 更容易編寫。然而,有一個(gè)領(lǐng)域幾乎沒有創(chuàng)新:服務(wù)器端 JavaScript 運(yùn)行時(shí)的文件系統(tǒng) API。kMh28資訊網(wǎng)——每日最新資訊28at.com

Node.js:當(dāng)今文件系統(tǒng) API 的起源

Node.js 最初發(fā)布于 2009 年,隨之誕生了 fs 模塊。fs 模塊是圍繞 Linux 的核心實(shí)用程序構(gòu)建的,其中的許多方法都反映了它們的 Linux 靈感,如 rmdir 、 mkdir 和 stat 。為此,Node.js 成功創(chuàng)建了一個(gè)低級文件系統(tǒng) API,可以處理開發(fā)人員希望在命令行上完成的任何事情。不幸的是,這就是創(chuàng)新的終點(diǎn)。kMh28資訊網(wǎng)——每日最新資訊28at.com

Node.js 文件系統(tǒng) API 最大的改變是引入了 fs/promises ,將整個(gè)實(shí)用程序從基于回調(diào)的方法移動(dòng)到基于 promise 的方法。較小的增量變化包括實(shí)現(xiàn) web 流和確保 reader 也實(shí)現(xiàn)了異步迭代器。該 API 仍然使用專有的 Buffer 類來讀取二進(jìn)制數(shù)據(jù)。(盡管 Buffer 現(xiàn)在是 Uint8Array 的子類,但仍然存在不兼容性,這使得使用 Buffers 有問題。)kMh28資訊網(wǎng)——每日最新資訊28at.com

即使是 Ryan Dhal 在 Node.js 上的繼任者 Deno,也沒有在文件系統(tǒng) API 上做太多的改進(jìn),它基本上遵循了與 Node.js 中的 fs 模塊相同的模式,盡管它使用了 Uint8Arrays,而 Node.js 使用了 Buffer s,并且在不同的地方使用了異步迭代器,但它仍然采用了與 Node.js 相同的低級 API 方法。kMh28資訊網(wǎng)——每日最新資訊28at.com

只有 Bun,作為服務(wù)器端 JavaScript 運(yùn)行時(shí)生態(tài)系統(tǒng)的最新成員,甚至嘗試使用 Bun.file() 來更新文件系統(tǒng) API,這是受 fetch() 的啟發(fā)。雖然我贊賞這種對如何使用文件的重新思考,但當(dāng)你處理多個(gè)文件時(shí),為每個(gè)想要處理的文件創(chuàng)建一個(gè)新對象可能會(huì)很麻煩(當(dāng)處理數(shù)千個(gè)文件時(shí),會(huì)有一個(gè)巨大的性能損失)。除此之外,Bun 希望你使用 Node.js fs 模塊進(jìn)行其他操作。kMh28資訊網(wǎng)——每日最新資訊28at.com

一個(gè)現(xiàn)代的文件系統(tǒng) API 會(huì)是什么樣子?

在花費(fèi)數(shù)年時(shí)間在維護(hù) ESLint 的同時(shí)與 Node.js fs 模塊斗爭之后,我問自己,一個(gè)現(xiàn)代的文件系統(tǒng) API 會(huì)是什么樣子?kMh28資訊網(wǎng)——每日最新資訊28at.com

  • 通常情況下會(huì)很簡單。至少 80%的時(shí)間,我不是讀取文件就是寫入文件,或者檢查文件是否存在,差不多就是這樣,然而這些操作充滿了危險(xiǎn),因?yàn)槲倚枰獧z查各種東西以避免錯(cuò)誤或記住額外的屬性(例如 { encoding: "utf8" } )。
  • 錯(cuò)誤將很少發(fā)生。我對 fs 模塊最大的抱怨就是它拋出錯(cuò)誤的頻率。在不存在的文件上調(diào)用 fs.stat() 會(huì)拋出錯(cuò)誤,這意味著你實(shí)際上需要將每個(gè)調(diào)用包裝在 try-catch 中。為什么?對于大多數(shù)應(yīng)用程序來說,缺少文件并不是不可恢復(fù)的錯(cuò)誤。
  • 行動(dòng)將是可觀察的。在測試文件系統(tǒng)操作時(shí),我真的只是想要一種方法來驗(yàn)證我期望發(fā)生的事情是否確實(shí)發(fā)生了。我不想與其他一些實(shí)用程序建立間諜網(wǎng)絡(luò),這些實(shí)用程序可能會(huì)也可能不會(huì)改變我正在觀察的方法的實(shí)際行為。
  • 模擬很容易。我總是驚訝于模擬文件系統(tǒng)操作的難度。最后我只能使用 proxyquire 之類的東西,否則就需要設(shè)置迷宮般的模擬,花上一段時(shí)間才能弄好。對于文件系統(tǒng)操作來說,這是一個(gè)很常見的需求,竟然還沒有解決方案。

帶著這些想法,我開始設(shè)計(jì) fsx。kMh28資訊網(wǎng)——每日最新資訊28at.com

FSX 基礎(chǔ)知識(shí)

fsx庫是我圍繞現(xiàn)代高級文件系統(tǒng) API 應(yīng)該是什么樣子的想法的結(jié)晶。在這一點(diǎn)上,它專注于支持最常見的文件系統(tǒng)操作,而把較少使用的操作(例如 chmod )拋在后面。(我并不是說這些操作在將來不會(huì)被添加,但對我來說,從最常見的情況開始,然后以與初始方法相同的謹(jǐn)慎方式構(gòu)建更多的功能是很重要的。)kMh28資訊網(wǎng)——每日最新資訊28at.com

使用 fsx 運(yùn)行時(shí)包

首先,fsx API 在三個(gè)運(yùn)行時(shí)包中可用。這些包都包含相同的功能,但綁定到不同的底層 API。這些包是:kMh28資訊網(wǎng)——每日最新資訊28at.com

  • fsx-node - Node.js 中 fsx API 的綁定
  • fsx-deno - fsx API 的 Deno 綁定
  • fsx-memory - 適用于任何運(yùn)行時(shí)(包括 web 瀏覽器)的內(nèi)存實(shí)現(xiàn)

所以,開始時(shí),你需要使用最適合你用例的運(yùn)行時(shí)包。為了本文的目的,我將專注于 fsx-node ,但相同的 API 存在于所有運(yùn)行時(shí)包中. 所有運(yùn)行時(shí)包都導(dǎo)出一個(gè) fsx 單例,你可以以類似于 fs的方式使用它。kMh28資訊網(wǎng)——每日最新資訊28at.com

import { fsx } from "node-fsx";

使用 fsx 讀取文件

文件是通過使用返回特定數(shù)據(jù)類型的方法來讀取的:kMh28資訊網(wǎng)——每日最新資訊28at.com

  • fsx.text(filePath) 讀取給定的文件并返回一個(gè)字符串。
  • fsx.json(filePath) 讀取給定的文件并返回一個(gè) JSON 值。
  • fsx.arrayBuffer(filePath) 讀取給定的文件并返回一個(gè) ArrayBuffer 。

這里有一些例子:kMh28資訊網(wǎng)——每日最新資訊28at.com

// read plain textconst text = await fsx.text("/path/to/file.txt");// read JSONconst json = await fsx.json("/path/to/file.json");// read bytesconst bytes = await fsx.arrayBuffer("/path/to/file.png");

如果文件不存在,每個(gè)方法都會(huì)返回 undefined 而不是拋出錯(cuò)誤。這意味著您可以使用 if 語句而不是 try-catch,并且可以選擇使用 nullish 合并運(yùn)算符來指定默認(rèn)值,如下所示:kMh28資訊網(wǎng)——每日最新資訊28at.com

// read plain textconst text = (await fsx.text("/path/to/file.txt")) ?? "default value";// read JSONconst json = (await fsx.json("/path/to/file.json")) ?? {};// read bytesconst bytes =  (await fsx.arrayBuffer("/path/to/file.png")) ?? new ArrayBuffer(16);

我覺得這種方法在 2024 年比不斷擔(dān)心不存在的文件出錯(cuò)更有 JavaScript 風(fēng)格。kMh28資訊網(wǎng)——每日最新資訊28at.com

使用 fsx 寫文件

要寫文件,調(diào)用 fsx.write() 方法。這個(gè)方法接受兩個(gè)參數(shù):kMh28資訊網(wǎng)——每日最新資訊28at.com

  • filePath:string - 寫入的路徑
  • value:string|ArrayBuffer - 寫入文件的值

這里有一個(gè)例子:kMh28資訊網(wǎng)——每日最新資訊28at.com

// write a stringawait fsx.write("/path/to/file.txt", "Hello world!");const bytes = new TextEncoder().encode("Hello world!").buffer;// write a bufferawait fsx.write("/path/to/file.txt", buffer);

作為額外的好處,fsx.write() 將自動(dòng)創(chuàng)建任何尚不存在的目錄。這是我經(jīng)常遇到的另一個(gè)問題,我認(rèn)為它應(yīng)該在現(xiàn)代文件系統(tǒng) API 中“正常工作”。kMh28資訊網(wǎng)——每日最新資訊28at.com

使用 fsx 檢測文件

要確定一個(gè)文件是否存在,使用 fsx.isFile(filePath) 方法,如果給定的文件存在,則返回 true ,否則返回 false 。kMh28資訊網(wǎng)——每日最新資訊28at.com

if (await fsx.isFile("/path/to/file.txt")) {  // handle the file}

與 fs.stat() 不同,如果文件不存在,這個(gè)方法會(huì)返回 false ,而不是拋出錯(cuò)誤。kMh28資訊網(wǎng)——每日最新資訊28at.com

try {  const stat = await fs.stat(filePath);  return stat.isFile();} catch (ex) {  if (ex.code === "ENOENT") {    return false;  }  throw ex;}

刪除文件和目錄

fsx.delete() 方法接受一個(gè)參數(shù),即要?jiǎng)h除的路徑,并且對文件和目錄都有效。kMh28資訊網(wǎng)——每日最新資訊28at.com

// delete a fileawait fsx.delete("/path/to/file.txt");// delete a directoryawait fsx.delete("/path/to");

fsx.delete() 方法故意過于激進(jìn):它會(huì)遞歸地刪除目錄,即使它們不是空的(實(shí)際上是 rmdir -r)。kMh28資訊網(wǎng)——每日最新資訊28at.com

fsx 日志

fsx 的一個(gè)關(guān)鍵特性是,由于其內(nèi)置的日志系統(tǒng),很容易確定哪些方法被調(diào)用,并使用了哪些參數(shù)。要啟用 fsx 實(shí)例的日志記錄,請調(diào)用 logStart() 方法并傳入一個(gè)日志名稱。當(dāng)你完成日志記錄時(shí),請調(diào)用 logEnd() 并傳入相同的名稱來檢索日志條目的數(shù)組。kMh28資訊網(wǎng)——每日最新資訊28at.com

fsx.logStart("test1");const fileFound = await fsx.isFile("/path/to/file.txt");const logs = fsx.logEnd("test1");

每個(gè)日志條目都是一個(gè)包含以下屬性的對象:kMh28資訊網(wǎng)——每日最新資訊28at.com

  • timestamp - 創(chuàng)建日志的數(shù)字時(shí)間戳
  • type - 描述日志類型的字符串
  • data - 與日志相關(guān)的附加數(shù)據(jù)

對于方法調(diào)用,日志條目的 type 是 call ,而 data 屬性是一個(gè)對象,包含:kMh28資訊網(wǎng)——每日最新資訊28at.com

  • methodName - 被調(diào)用的方法的名稱
  • args - 傳遞給方法的參數(shù)數(shù)組。

對于前面的例子, logs 將包含一個(gè)條目:kMh28資訊網(wǎng)——每日最新資訊28at.com

// example log entry{    timestamp: 123456789,    type: "call",    data: {        methodName: "isFile",        args: ["/path/to/file.txt"]    }}

了解這一點(diǎn)后,您可以輕松地在測試中設(shè)置日志記錄,然后檢查調(diào)用了哪些方法,而無需使用第三方間諜庫。kMh28資訊網(wǎng)——每日最新資訊28at.com

使用 fsx impls

fsx 的設(shè)計(jì)是這樣的,抽象的核心功能包含在 fsx-core 包中,每個(gè)運(yùn)行時(shí)包都擴(kuò)展了該功能,使用特定于運(yùn)行時(shí)的文件系統(tǒng)操作實(shí)現(xiàn),這些操作被包裝在一個(gè)稱為 impl 的對象中。kMh28資訊網(wǎng)——每日最新資訊28at.com

  1. fsx 單例
  2. 一個(gè)構(gòu)造函數(shù),可以創(chuàng)建 fsx 的另一個(gè)實(shí)例(比如 fsx-node 中的 NodeFsx )
  3. 一個(gè)構(gòu)造函數(shù),可以創(chuàng)建運(yùn)行時(shí)包的 impl 實(shí)例(如 node-fsx 中的 NodeFsxImpl )。

這可以讓您只使用所需的功能。kMh28資訊網(wǎng)——每日最新資訊28at.com

fsx 中的 base impls 和 active impls

每個(gè) fsx 實(shí)例都有一個(gè) base 類實(shí)現(xiàn),它定義了 fsx 對象在生產(chǎn)環(huán)境中的行為。active impls 是在任何給定時(shí)間使用的實(shí)現(xiàn),它可能也是 base 類實(shí)現(xiàn),也可能不是。你可以調(diào)用 fsx.setImpl()來改變 active impls。kMh28資訊網(wǎng)——每日最新資訊28at.com

import { fsx } from "fsx-node";fsx.setImpl({  json() {    throw Error("This operation is not supported");  },});// somewhere elseawait fsx.json("/path/to/file.json"); // throws error

在此示例中,基本實(shí)現(xiàn)被替換為自定義實(shí)現(xiàn),該自定義實(shí)現(xiàn)在調(diào)用 fsx.json() 方法時(shí)會(huì)引發(fā)錯(cuò)誤。這使得您可以輕松地模擬測試方法,而不必?fù)?dān)心它可能如何影響整個(gè)包含的 fsx 對象。kMh28資訊網(wǎng)——每日最新資訊28at.com

交換 impls 進(jìn)行測試

假設(shè)你有一個(gè)名為 readConfigFile() 的函數(shù),它使用了來自 node-fsx 的 fsx 單例來讀取名為 config.json 的文件,當(dāng)測試這個(gè)函數(shù)時(shí),你不想讓它實(shí)際訪問文件系統(tǒng),你可以把 fsx 的實(shí)現(xiàn)換成 fsx-memory 提供的內(nèi)存文件系統(tǒng)實(shí)現(xiàn),如下:kMh28資訊網(wǎng)——每日最新資訊28at.com

import { fsx } from "fsx-node";import { MemoryFsxImpl } from "fsx-memory";import { readConfigFile } from "../src/example.js";import assert from "node:assert";describe("readConfigFile()", () => {    beforeEach(() => {        fsx.setImpl(new MemoryFsxImpl());    });    afterEach(() => {        fsx.resetImpl();    });    it("should read config file", async () => {        await fsx.write("config.json", JSON.stringify({ found: true });        const result = await readConfigFile();        assert.isTrue(result.found);    });});

這就是使用 fsx 在內(nèi)存中模擬整個(gè)文件系統(tǒng)是多么容易。您不必像模塊加載器攔截那樣擔(dān)心導(dǎo)入所有測試模塊的順序,也不需要經(jīng)歷包含模擬庫的過程以確保一切正常。您只需更換測試的 impl,然后再重置它。通過這種方式,您可以以更高性能且不易出錯(cuò)的方式測試文件系統(tǒng)操作。kMh28資訊網(wǎng)——每日最新資訊28at.com

命名注意事項(xiàng)

不幸的是,在我發(fā)布 fsx 的時(shí)候,亞馬遜發(fā)布了一款名為 FSx[2] 的產(chǎn)品。如果它獲得任何支持,我可能會(huì)重命名這個(gè)庫,歡迎提出建議。kMh28資訊網(wǎng)——每日最新資訊28at.com

希望得到結(jié)論和反饋

長期以來,我們一直在使用 JavaScript 運(yùn)行時(shí)中笨拙的低級文件系統(tǒng) API。fsx 庫是我嘗試重新想象現(xiàn)代文件系統(tǒng) API 的樣子,如果我們花一些時(shí)間關(guān)注最常見的情況,并改進(jìn) JavaScript 語言目前提供的人體工學(xué)設(shè)計(jì)。通過從頭開始重新思考,我認(rèn)為 fsx 為我們提供了一種更愉快的文件系統(tǒng)體驗(yàn)。kMh28資訊網(wǎng)——每日最新資訊28at.com

基礎(chǔ)庫只關(guān)注我最常用的方法,但我計(jì)劃在了解和思考用例后添加更多方法。您今天就可以試用,歡迎反饋。我很想知道你的想法!kMh28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-66538-0.htmlfsx 簡介:適用于 JavaScript 的現(xiàn)代文件系統(tǒng) API

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: AI 跟誰嘮跟誰嘮,順網(wǎng)嘮嘮打造 AI 趣味新體驗(yàn)!

下一篇: 實(shí)戰(zhàn)Arthas:常見命令與優(yōu)秀實(shí)踐

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 纳雍县| 蒲江县| 清水河县| 沙坪坝区| 丹巴县| 乐陵市| 桦南县| 陆良县| 文成县| 同仁县| 余江县| 岳普湖县| 南召县| 诸暨市| 易门县| 宁武县| 简阳市| 岳普湖县| 蒙城县| 仙桃市| 城口县| 东兰县| 息烽县| 特克斯县| 西充县| 江川县| 石首市| 佛山市| 宿迁市| 任丘市| 河北省| 南华县| 平原县| 磐石市| 长治市| 罗江县| 基隆市| 凌云县| 澳门| 涿鹿县| 武川县|