JavaScript NodeJS如何在异步函数中使用流/承诺?

aoyhnmkz  于 2023-01-16  发布在  Java
关注(0)|答案(3)|浏览(233)

我在Node中有一个JS异步函数。比如说,它从URL下载一个文件,并对它做一些事情,比如解压缩。我这样写它,它工作正常,但是eslint让我感觉到有一股浓厚的代码味道:error Promise executor functions should not be async no-async-promise-executor. Async是必需的,因为await fetch在身体功能中。
我对streamsasync/await都不够熟练,无法自己纠正它。我想摆脱Promise,完全使用async/await。模块stream/promises似乎是从Node-15开始的方法,正如这里所评论的how-to-use-es 8-async-wait-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);
    }
  });
}
ybzsozfc

ybzsozfc1#

您可以在进入执行器之前简单地执行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((resolve, reject) => {
    body.on('error', reject);
    body.on('finish', resolve);
  });
  
};

一般来说,我的建议是从承诺执行者中删除尽可能多的代码。在这种情况下,承诺只是捕获解决/拒绝所必需的。
请注意,我还从doSomething中删除了doWhatever-这使doSomething更加健壮。

doSomething('http://example.com').then(doWhatever);

最后,我建议您将someFile设置为doSomething的参数,而不是从更广泛的上下文引用它!

lb3vh1jj

lb3vh1jj2#

要使用您正在寻找的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';
}
dkqlctbz

dkqlctbz3#

您可以在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';
  });
}

相关问题