等待承诺内部循环

Jum*_*mpa 7 javascript node.js promise async-await bluebird

let currentProduct;

for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i];

    subscription.getAll(products[i]._id)
        .then((subs) => {
            update(subs, currentProduct);
        });
}
Run Code Online (Sandbox Code Playgroud)

我正在使用bluebird,方法getAll更新返回promise.我怎么说"等到两个承诺返回,然后更新currentProduct值"?我对JS很新...

CRi*_*ice 13

如果您可以使用async/,这将是直截了当的await:

// Make sure that this code is inside a function declared using
// the `async` keyword.
let currentProduct;

for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i];

    // By using await, the code will halt here until
    // the promise resolves, then it will go to the
    // next iteration...
    await subscription.getAll(products[i]._id)
        .then((subs) => {
            // Make sure to return your promise here...
            return update(subs, currentProduct);
        });

    // You could also avoid the .then by using two awaits:
    /*
    const subs = await subscription.getAll(products[i]._id);
    await update(subs, currentProduct);
    */
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您只能使用普通承诺,则可以遍历所有产品,并将每个承诺放在.then最后一个循环中.这样,它只会在前一个已经解决的情况下前进到下一个(即使它将首先迭代整个循环):

let currentProduct;

let promiseChain = Promise.resolve();
for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i];

    // Note that there is a scoping issue here, since
    // none of the .then code runs till the loop completes,
    // you need to pass the current value of `currentProduct`
    // into the chain manually, to avoid having its value
    // changed before the .then code accesses it.

    const makeNextPromise = (currentProduct) => () => {
        // Make sure to return your promise here.
        return subscription.getAll(products[i]._id)
            .then((subs) => {
                // Make sure to return your promise here.
                return update(subs, currentProduct);
            });
    }

    // Note that we pass the value of `currentProduct` into the
    // function to avoid it changing as the loop iterates.
    promiseChain = promiseChain.then(makeNextPromise(currentProduct))
}
Run Code Online (Sandbox Code Playgroud)

在第二个片段中,循环只是设置整个链,但不会.then立即执行代码.您的getAll功能将不会运行,直到每个先前的功能轮流解决(这是您想要的).


Ben*_*aum 7

我是这样做的:

for (let product of products) { 
  let subs = await subscription.getAll(product._id);
  await update(subs, product);
}
Run Code Online (Sandbox Code Playgroud)

无需手动链接promises或按索引迭代数组:)

  • 我正在尝试你的代码,我认为它更优雅.无论如何,你错过了"让"产品里面的产品.我注意到,因为我收到了UnhandledPromiseRejectionWarning ...你可以编辑你的代码并添加一些东西来处理承诺拒绝吗?提前谢谢了.编辑:没关系我应该使用try/catch ... (2认同)