JavaScript NodeJS 如何将流/承诺与异步函数一起使用?
Posted
技术标签:
【中文标题】JavaScript NodeJS 如何将流/承诺与异步函数一起使用?【英文标题】:JavaScript NodeJS How to use stream/promises with async functions? 【发布时间】:2021-11-16 04:16:42 【问题描述】:我在 Node.js 中有一个 JS 异步函数。比如说,它从一个 URL 下载一个文件并用它做一些事情,例如。解压它。我是这样写的,它可以工作,但是eslint
向我展示了一股浓浓的代码味道:error Promise executor functions should not be async no-async-promise-executor
。 Async
是必需的,因为 await fetch
在 body 函数中。
我对@987654326@ 和async/await
不够熟练,无法自行纠正。我想摆脱 Promise 并充分使用 async/await
。模块stream/promises
似乎是从Node-15 开始的方式,正如这里how-to-use-es8-async-await-with-streams 所评论的那样。在这种情况下如何使用await pipeline(...)
?也许有更好更短的方法?
函数如下:
function doSomething(url)
return new Promise(async (resolve, reject) =>
try
const fileWriteStream = fs.createWriteStream(someFile,
autoClose: true,
flags: 'w',
);
const res = await fetch(url);
const body = res.body;
body
.pipe(fileWriteStream)
.on('error', (err) =>
reject(err);
)
.on('finish', async () =>
await doWhatever();
resolve('DONE');
);
catch (err)
reject(err);
);
【问题讨论】:
不确定这是否是您的问题,但async function doSomething
对您没有任何作用......它应该只是function doSomething
,因为您返回Promise
嗯,是的,我从一些较大的代码中提取了该函数,但这确实是题外话。我正在从我的示例中删除它。
【参考方案1】:
您可以在 NodeJS 中使用 fs/promises
并将您的代码精简为以下内容:
import writeFile from 'fs/promises'
async function doSomething(url)
const res = await fetch(url);
if (!res.ok) throw new Error('Response not ok');
await writeFile(someFile, res.body, encoding: 'utf-8')
await doWhatever();
return 'DONE';
);
【讨论】:
您使用fetch(url).then
避免使用async (resolve, reject) =>...
,但我的问题是仅在函数体中使用async/await
和await fetch(url)
?或者作为替代方案,如果可能的话,使用stream/promises
pipeline
函数?
抱歉。我已经更新了我的答案。流对于您想要完成的简单事情来说有点多
谢谢!我不知道writeFile
。代码更干净! pipeline
和 createWriteStream
是否也可行,例如 pipeline( ~fetch as a stream~, fs.createWriteStream)
?
我正在使用命名导入 - import writeFile from 'fs/promises';
。您也可以使用import fs from 'fs/promises';
,并且您会以 Promise 的形式获得大部分文件系统 API。然后您可以等待大多数文件系统操作:await fs.writeFile(...);
。此外,如果这解决了您的问题,接受答案是有礼貌的,这样其他人就知道它有效。干杯!
我当然会!谢谢!到目前为止仍在消化答案。【参考方案2】:
您可以在到达执行程序之前简单地执行await
:
async function doSomething(url)
const fileWriteStream = fs.createWriteStream(someFile, autoClose: true, flags: 'w' );
let body = await fetch(url);
body.pipe(fileWriteStream);
return new Promise((reject, resolve) =>
body.on('error', reject);
body.on('finish', resolve);
);
;
总的来说,我的建议是从你的承诺执行者中删除尽可能多的代码。在这种情况下,Promise 仅用于捕获解决/拒绝。
请注意,我还从doSomething
中删除了doWhatever
- 这使得doSomething
更加健壮。你可以这样做:
doSomething('http://example.com').then(doWhatever);
最后我建议您将someFile
设置为doSomething
的参数,而不是从更广泛的上下文中引用它!
【讨论】:
谢谢。您的代码确实非常干净,并且与我可怜的代码相反。对不起someFile
发错地方了,写好sn-p的辛苦工作中的一个错误。【参考方案3】:
要使用您正在寻找的pipeline
函数,它会是
const pipeline = require('stream/promises');
async function doSomething(url)
const fileWriteStream = fs.createWriteStream(someFile,
autoClose: true,
flags: 'w',
);
const res = await fetch(url);
await pipeline(res.body, fileWriteStream);
await doWhatever();
return 'DONE';
【讨论】:
以上是关于JavaScript NodeJS 如何将流/承诺与异步函数一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
NodeJS 中的 Firebase javascript 承诺
如何使用 Bluebird 承诺 NodeJS Express
一个承诺的 mysql 模块将如何与 NodeJS 一起工作?