繁体   English   中英

NodeJS-在Array.map中使用带有'if'语句的Async / Await

[英]NodeJS - Using Async/Await inside Array.map with 'if' statement

我有一个遍历对象的递归函数。 它寻找名称为subcomponent键(始终是一个数组),并对每个subcomponent的子代执行异步功能,其输出用于替换子代的数据。

在下面的示例中, populateSubcomponent()是异步函数。

码:

async function doPopulate(data) {
    Object.keys(data).map((key) => {
        if (typeof data[key] === 'object') { // We want to do a recursive check on the data so are interested in any objects (arrays) at this point
            if (key === 'subcomponent') { // If we have an object (array) with key `subcomponent` we want to populate each of its children
                const promises = data[key].map(subcomponent => populateSubcomponent(subcomponent));
                return Promise.all(promises).then((output) => {
                    data[key] = output;
                    console.log('1');
                });
            }
            doPopulate(data[key]); // Check recursively
            console.log('2');
        }
        console.log('3');
        return data;
    });
}
doPopulate(data);

我的期望是每一个的console.log号应该依次开火,而是我得到23 ,然后1 结果,递归函数在异步函数完成之前运行,因此永远不要按预期替换子级。 我在1处得到正确的结果,但未传递给23

如何最好地将递归doPopulate()调用与if语句合并在一起?

我看过以下SO帖子:

但我无法将任何答案与自己的问题相关联,这主要是由于以下事实:我在递归函数中有一个if语句,而且我不确定如何在异步内容中处理该问题。

编辑

感谢大家的评论,我提出了以下建议:

async function doPopulate(data) {
    const promisesOuter = Object.keys(data).map(async (key) => {
        if (typeof data[key] === 'object') { // We want to do a recursive check on the data so are interested in any objects (arrays) at this point
            if (key === 'subcomponent') { // If we have an object (array) with key `subcomponent` we want to populate each of its children
                const promisesInner = data[key].map(subcomponent => populateSubcomponent(subcomponent));
                data[key] = await Promise.all(promisesInner);
            }
            await doPopulate(data[key]); // Check recursively
        }
        return data;
    });
    return Promise.all(promisesOuter);
}
return doPopulate(data);

由于这一切都发生在NodeJS流中(使用through2 ),所以我还需要使流功能异步:

const through = require('through2');

return through.obj(async (file, enc, done) => {
    const data = JSON.parse(file.contents.toString());
    await doPopulate(data);
    file.contents = Buffer.from(JSON.stringify(data));
    return done(null, file);
});

只要下一个承诺依赖于前一个承诺,您就必须顺序等待每个承诺。 如果可以同时完成它们,则只需汇总承诺并与Promise.all一起等待它们。 顺便说一下,如果需要使用await则只需要async关键字。 否则,没有理由使函数async

如果您想顺序等待每个诺言,则可以这样重写它:

function doPopulate(data) {
    return Object.keys(data).map(async (key) => {
        if (typeof data[key] === 'object') { // We want to do a recursive check on the data so are interested in any objects (arrays) at this point
            if (key === 'subcomponent') { // If we have an object (array) with key `subcomponent` we want to populate each of its children
                const promises = data[key].map((subcomponent) =>
                    populateSubcomponent(subcomponent)
                );
                data[key] = await Promise.all(promises);
                console.log('1');
            }
            await doPopulate(data[key]); // Check recursively
            console.log('2');
        }
        console.log('3');
        return data;
    });
}

事实证明,我需要返回两组诺言,如@Bergi在评论中建议的那样:

async function doPopulate(data) {
    const promisesOuter = Object.keys(data).map(async (key) => {
        if (typeof data[key] === 'object') { // We want to do a recursive check on the data so are interested in any objects (arrays) at this point
            if (key === 'subcomponent') { // If we have an object (array) with key `subcomponent` we want to populate each of its children
                const promisesInner = data[key].map(subcomponent => populateSubcomponent(subcomponent));
                data[key] = await Promise.all(promisesInner);
            }
            await doPopulate(data[key]); // Check recursively
        }
        return data;
    });
    return Promise.all(promisesOuter);
}
return doPopulate(data);

由于这一切都发生在NodeJS流中(使用through2 ),所以我还需要使流功能异步:

return through.obj(async (file, enc, done) => {
    const data = JSON.parse(file.contents.toString());
    await doPopulate(data);
    file.contents = Buffer.from(JSON.stringify(data));
    return done(null, file);
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM