等待承诺的 fs.writeFile 与 fs.writeFileSync
Posted
技术标签:
【中文标题】等待承诺的 fs.writeFile 与 fs.writeFileSync【英文标题】:Await promisified fs.writeFile vs fs.writeFileSync 【发布时间】:2019-04-19 15:08:09 【问题描述】:其中一个选项有什么优点吗?
1.
const fs = require('fs')
const testFunc1 = async () =>
fs.writeFileSync('text.txt', 'hello world')
2.
const fs = require('fs')
const util = require('util')
const writeFilePromisified = util.promisify(fs.writeFile)
const testFunc2 = async () =>
await writeFilePromisified('text.txt', 'hello world')
我知道 writeFile 和 writeFileSync 之间的区别。问题是返回 testFunc1 和 testFunc2 的 Promise 之间是否存在一些差异。所以打电话是一样的吗 testFunc1.then(...) // 或等待 testFunc1 要么 testFunc2.then(...) // 或者等待 testFunc2
当文件写入完成时,这两个承诺都将得到满足。
【问题讨论】:
【参考方案1】:fs.writeFileSync( file, data, options )
fs.writeFile( file, data, options, callback)
异步函数最后一个回调函数 表示异步函数完成的参数。
The ‘fs’ module implements the File I/O operation. Methods in the fs module can be synchronous as well as asynchronous.
开发人员更喜欢异步方法而不是同步方法,因为他们在程序执行期间从不阻塞程序,而后者会阻塞。在 Node.js 中阻塞主线程是“malpractice”,因此同步函数只能用于“debugging”或没有其他选项可用时。
fs.writeFileSync() 是一种同步方法,如果出现则创建一个新文件 指定的文件不存在,而 fs.writeFile() 是 异步方法。
【讨论】:
【参考方案2】:fs
已经包含不需要promisify
的promisified API。
const fsPromises = require("fs/promises");
await fsPromises.writeFile(file, data[, options])
基于 Promise 的异步版本需要将其用作基于 Promise 的控制流的一部分,而同步版本不强制此要求。
异步 readFile
/writeFile
是非阻塞的,而同步 readFileSync
/writeFileSync
是阻塞的,但可以更快地完成作业。这在密集的 IO 操作期间可能会很明显。
【讨论】:
fs.promise API 对于节点 10 是实验性的。 请您解释一下返回 testFunc1 和 testFunc2 的两个 Promises 之间的区别。我可以看到那里没有差异。testFunc1()
没用。它不会从承诺中受益。它阻塞了主线程,因为writeFileSync
是同步的。如果得到的承诺是await
ed,则提供一个微小的延迟。【参考方案3】:
writeFile() 和 writeFileSync() 之间的区别正如其他 writeFileSync() “阻塞”所解释的那样。那么,“阻塞”和“不阻塞”有什么区别呢?
我写了一个小测试,比较了 writeFile() 和 writeFileSync() 的速度。我测量了 writeFileSync() 返回结果所用的时间与从调用 writeFile() 到调用其回调参数所用的时间。令我(最初)惊讶的是,两者之间没有明显的区别。 writeFile() 似乎并不比 writeFileSync() 快。那么,当它似乎使我的程序流程复杂化时,我为什么要使用它呢?
但是,如果我不等待它的回调参数被调用,我测量了 writeFile() 所花费的时间。速度有很大差异,可能是 10 倍。
因此差别很大或没有差别取决于程序的其余部分。如果您对 writeFileSync() 的调用需要很长时间,那么您的程序在等待 writeFileSync() 返回时将无能为力。如果您执行 writeFile() 并在执行其他任何操作之前等待回调完成,则结果没有什么不同。但是如果你不(不需要)等待它的回调被调用,writeFile() 会快得多。
如果您编写某种调用 writeFileSync() 的服务器,这将有很大的不同。服务器在等待 writeFileSync() 完成时无法为任何新请求提供服务。如果大多数请求导致调用 writeFileSync(),这可能会对您的服务器性能产生重大影响。
【讨论】:
【参考方案4】:为了说明两个返回函数的promise之间的区别:
const fs = require('fs')
const util = require('util')
const testFunc1 = async () =>
fs.writeFileSync('text.txt', 'hello world')
console.log('file write done with writeFileSync')
const writeFilePromisified = util.promisify(fs.writeFile)
const testFunc2 = async () =>
await writeFilePromisified('text.txt', 'hello world')
console.log('file write done with promisified writeFile')
console.log('start test1')
testFunc1().then(() =>
console.log('promise 1 is fullfiled')
)
console.log('start test2')
testFunc2().then(() =>
console.log('promise 2 is fullfiled')
)
console.log('stop')
输出将是:
start test1
file write done with writeFileSync
start test2
stop
promise 1 is fullfiled
file write done with promisified writeFile
promise 2 is fullfiled
所以就像 estus 所说的 testFunc1 阻止了主线程的执行。 testFunc2 不阻塞。
【讨论】:
【参考方案5】:fs.readFile
采用回调函数,这意味着它不会阻止脚本的执行。
fs.readFileSync
但是 不 接受回调,这意味着脚本的执行将暂停,直到进程完成。
使用 promisfy 是解决此问题的一种方法,对于小文件它不会产生影响,但对于大文件,您可能希望将 fs.readFileSync
转换为 Promise,这样您就不会阻止执行。
希望对您有所帮助。
【讨论】:
以上是关于等待承诺的 fs.writeFile 与 fs.writeFileSync的主要内容,如果未能解决你的问题,请参考以下文章
为啥节点 10 强制在 fs.writeFile() 上传递回调?