【问题标题】:Node JS async/await with multiple fs.writeFile using through2 (Gulp/Vinyl)Node JS async/await 与多个 fs.writeFile 使用 through2 (Gulp/Vinyl)
【发布时间】:2018-07-09 20:31:15
【问题描述】:

我正在使用through2 从 Gulp 流中生成多个文件。我正在使用 NodeJS 10.6.0,所以我想我会充分利用 async/await,但我还没有完全理解其中的机制。目前 through2 done() 回调在所有文件被写入之前被触发。

这是我所拥有的(简化的) - 请注意,我没有在最后返回流,因为没有必要。

async function createDirectory(pathDir) {
    return new Promise((resolve, reject) => {
        mkdirp(pathDir, (err) => {
            if (err) reject(err);
            else resolve();
        });
    });
}

async function writeFile(outputFilePath, outputFileContent) {
    return new Promise((resolve, reject) => {
        fs.writeFile(outputFilePath, outputFileContent, (err) => {
            if (err) reject(err);
            else resolve();
        });
    });
}

async function doWriteFile(outputFolderPath, outputFilePath, outputContent) {
    await createDirectory(outputFolderPath);
    await writeFile(outputFilePath, outputContent, outputContent);
}

async function doGenerateVariant(data, variantArr) {
    for (const variant of variantArr) {

        /* Do a load of stuff */

        const variantOutputFolderPath = blah;
        const variantOutputFilePath = blah;
        const variantOutputContent = blah;

        await doWriteFile(variantOutputFolderPath, variantOutputFilePath, variantOutputContent);
    }
}

const generateVariant = () => {
    return through.obj((file, enc, done) => {
        const data = JSON.parse(file.contents.toString());

        */ Do a load of stuff */

        const { variant } = data;
        const variantArr = Object.values(variant);
        doGenerateVariant(data, variantArr);
        return done();
    });
};

这不起作用,因为 done() 在所有文件都被写入之前被返回。我猜我错过了一两个回报,但我所做的一切似乎都没有奏效。

如果我将done() 传递给doGenerateVariant 并在doWriteFile 之后调用它,一切都会按预期进行,但我知道这是不正确的。

【问题讨论】:

    标签: javascript node.js gulp async-await through2


    【解决方案1】:

    在调用done 之前,您需要等待doGenerateVariant 完成其工作。记住async 函数总是返回一个 Promise。所以你可以这样做

    const generateVariant = () => {
        return through.obj((file, enc, done) => {
            const data = JSON.parse(file.contents.toString());
    
            */ Do a load of stuff */
    
            const { variant } = data;
            const variantArr = Object.values(variant);
            doGenerateVariant(data, variantArr).then(() => done());
        });
    };
    

    或使用async/await

    const generateVariant = () => {
        return through.obj(async (file, enc, done) => {
            const data = JSON.parse(file.contents.toString());
    
            */ Do a load of stuff */
    
            const { variant } = data;
            const variantArr = Object.values(variant);
            await doGenerateVariant(data, variantArr);
            done();
        });
    };
    

    【讨论】:

    • 完美!正是我需要的。谢谢! :)
    • 虽然有一个问题...我在doGenerateVariant 中有await doWriteFile 和eslint 状态“对可迭代的每个元素执行操作是一项常见任务。但是,执行等待作为一部分每次操作都表明程序没有充分利用异步/等待的并行化优势。”这是否意味着我的函数没有充分利用 async/await?
    • @GarethJames 它说你一次写一个文件。 await 停止函数执行,直到等待的承诺得到解决。如果您想并行编写文件,您可以将所有 variantArr 转换为 Promise 并等待所有 await Promise.all(variantArr.map(variant => { your logic; return doWriteFile(...)}))
    • @GarethJames 没问题。很高兴我能帮忙:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 2019-05-23
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    相关资源
    最近更新 更多