动态填充Promise.all()

时间:2018-06-11 09:30:43

标签: javascript asynchronous promise

我试图弄清楚为什么这段代码不起作用。我循环遍历依赖树(deepObject),对于每一个我想运行一个返回promise的函数。然后我希望在解决所有promise之后发生下一组函数,但是promise.all中的控制台日志没有执行。 ES6也很酷,如果你有更好的方法,但我也很想知道为什么这段代码不起作用。

已更新为添加.catch(这没有效果)

for (let i = 0; i < keys.length; i++) {
    promisesArray.push(promiseFunction(deepObject[keys[i]]));
}
Promise.all(promisesArray).then(resolved => {
    console.log('dep promises resolved');
    console.log(`resolved: ${JSON.stringify(resolved)}`);
}).catch(err => console.error(new Error(err));

// promiseFunction is recursive
promiseFunction(obj) {
    return new Promise((resolve, reject) => {

        const keys = Object.keys(deepObj);
        for (let j = 0; j < keys.length; j++) {
            if (Object.keys(deepObj[keys[j]]).length) {
                // adding return statement to following line breaks it
                // that was already recommended, see threads
                promiseFunction(deepObj[keys[j]]);
            } else {
                const dep = new Package(keys[j]);
                console.log(`skan dep: ${keys[j]}`);
                dep.fetch().then(() => {
                    return anotherFunction();
                }).then(() => {
                    return Promise.all([
                        promise1(),
                        promise2(),
                        promise3(),
                    ]).then(resolved => {
                        if (resolved[0].propertyINeed) {
                            resolve(true);
                        }
                        resolve(false);
                    });
                }).catch(err => {
                    console.error(new Error(err));
                    process.exit(1);
                });
            }
        }
    });

我知道这次对话 - has been discussed - on here before

在上面的第二个链接中,接受的答案表明:

  

如果你异步填充数组,你应该获得该数组的承诺,并使用.then(Promise.all.bind(Promise))。如果你不知道什么时候停止添加承诺,那么这是不可能的,因为它们可能永远都不会得到解决。

但是我没有使用异步来填充数组。我需要这个吗?我在这里缺少什么?

更新

由于我现在在.then()以及.catch()中都有错误记录,因此似乎出现了与内部发生的事情无关的错误。

promiseFunction(deepObj[keys[j]]);之前添加return语句打破了递归。我从迭代超过173个对象到68.添加捕获记录没有其他结果。上面的代码已更新,以分享更多的递归fn。当我运行它时,它似乎执行所有的承诺,但我无法知道这一点。我最关心的是知道1. promise.all的promise数组包含它应该包含的所有对象,以及2.捕获递归对象中所有对象的所有promise都被解析的时刻。

此外,对于记录,返回promise的这些函数中的每一个都必须是异步的。我已经多次回过头来试图简化并删除任何不必要的承诺。任务很复杂。必须执行一系列步骤,它们是异步的,并且它们是链接的,因为它们必须按特定顺序解析。

2 个答案:

答案 0 :(得分:2)

if (Object.keys(obj[keys[j]]).length) {
    promiseFunction(obj[keys[j]]);
} else {
    // and some more async hell that all resolves correctly

如果Object.keys(obj[keys[j]]).lengthtrue,那么您永远不会致电resolvereject,以便承诺永远不会解决。

(请注意,调用promiseFunction会递归地创建一个 new 承诺,该承诺永远不会放入Promise.all)。

由于您的某些承诺无法解决,Promise.all也不会。

您可能需要更多内容:

var promises = [];
processObject(obj);
Promise.all(promises).then(etc etc);

function processObject(object) {
    for ( loop; over; object ) {
        if (condition) {
             processObject(object[something]);
        } else {
             promises.push(new Promise( (res, rej) => {
                 // so something async
             });
        }
    }
}

答案 1 :(得分:0)

让我们来看看你的promiseFunction ...

for (let j = 0; j < keys.length; j++) {
    if (Object.keys(obj[keys[j]]).length) {
        //if you get in here, promiseFunction returns undefined, and it never gets resolved
        promiseFunction(obj[keys[j]]);
    } else {
        const dep = new Package(keys[j]);
        console.log(`skan dep: ${keys[j]}`);
        // and some more async hell that all resolves correctly
        //but even if it resolves correctly, you still have the if...
    }
}

要做到这一点,只需在if语句中返回promiseFunction结果:

for (let j = 0; j < keys.length; j++) {
    if (Object.keys(obj[keys[j]]).length) {
        //if you get in here, you're saying this promise will depend on how this second promiseFunction will resolve
        return promiseFunction(obj[keys[j]]);
    } else {
        //omitted for brevity...
        resolve('your value');
    }
}

现在,当你进入if语句时,你基本上是根据第二个promiseFunction是否已经正确解决而告知解决的承诺 - 你将解决方案委托给另一个Promise。

我从来没有听过有人给它这个名字,但你可以把它想象成Promise递归:)