Promise all 中的同步循环 [英] Synchronous loop in Promise all

查看:173
本文介绍了Promise all 中的同步循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的代码的一部分中做一个同步循环.函数 saveInDatabase 检查项目标题(字符串)是否已存在于数据库中.这就是不能并行解决的原因,否则条件将永远不适用(并且会产生重复项).

I would like to do a synchronous loop in a part of my code. The function saveInDatabase checks if the item title (string) already exists in the database. That's why it can't be resolved in parallel, otherwise the condition will never apply (and would create duplicates).

Promise.all(arr.map(item => {
     saveInDatabase(item).then((myResult) => ... );
}));

我试过把这个函数封装成单独的promise,也试过用npm包(synchronous.js,sync),但是好像不适合我的代码.

I tried to encapsulate this function into separate promises, also tried with npm packages (synchronous.js, sync), but it seems that it does not fit with my code.

也许这个解决方案是完全愚蠢的.您认为将 promise.all 替换为同步循环(例如 foreach)是否更好?问题是我需要每次迭代的结果...

Maybe this solution is completely silly. Do you think it's a better idea to replace promise.all by a synchronous loop (foreach for example) ? The problem is that I need the results of each iteration...

我使用的是 Node 6.11.2.你能给我一些处理这个问题的技巧吗?先感谢您.

I'm using Node 6.11.2. Could you give me some tips to handle that ? Thank you in advance.

推荐答案

不使用 await(在 node.js v6.11.2 中没有,但会使这更简单),一个经典的模式序列化一堆返回承诺的异步操作是使用 reduce() 循环这样的:

Without using await (which is not in node.js v6.11.2, but would make this simpler), a classic pattern for serializing a bunch of async operations that return a promise is to use a reduce() loop like this:

arr.reduce(function(p, item) {
    return p.then(function() {
        return saveInDatabase(item).then((myResult) => ... );
    });
}, Promise.resolve()).then(function() {
    // all done here
}).catch(function(err) {
    // error here
});

如果你想保存所有的结果,你可以使用你的 .then(myResult => ...) 处理程序将结果 .push() 转化为完成后可以访问的数组.

If you want to save all the results, you can use your .then(myResult => ...) handler to .push() the result into an array which you can access when done.

这会将所有对 saveInDatabase(item) 的调用序列化为它在调用第二个之前等待第一个完成,在调用第三个之前等待第二个完成等等...

This will serialize all the calls to saveInDatabase(item) to it waits for the first one to be done before calling the second one, waits for the second one to be done before calling the third one, etc...

如果 saveInDatabase(item) 拒绝,这里的默认实现将停止.如果你想继续(你没有在你的问题中说),即使它给出了一个错误,那么你可以添加一个 .catch() 到它来将被拒绝的承诺变成一个已履行的承诺承诺.

The default implementation here will stop if saveInDatabase(item) rejects. If you want to keep going (you don't say in your question), even when it gives an error, then you can add a .catch() to it to turn the rejected promise into a fulfilled promise.

在 node.js v7+ 中,您可以在常规的 for 循环中使用 await:

In node.js v7+, you can use await in a regular for loop:

async function myFunc() {
    let results = [];
    for (let item of arr) {
        let r = await saveInDatabase(item).then((myResult) => ... );
        results.push(r);
    }
    return results;
}

myFunc().then(function(results) {
    // all done here
}).catch(function(err) {
    // error here
});

<小时>

如果您可以并行运行所有请求,那么您可以这样做:


If you could run all the requests in parallel, then you could do that like this:

Promise.all(arr.map(item => {
     return saveInDatabase(item).then((myResult) => ... );
})).then(function(results) {
    // all done here
}).catch(function(err) {
    // error here
});

在其中任何一个中,如果您不希望它在拒绝时停止,则将 .catch() 添加到您的 saveInDatabase() 承诺链以将拒绝转换为已解决的承诺,其中包含一些您可以检测到的已知值或错误值.

In any of these, if you don't want it to stop upon a rejection, then add a .catch() to your saveInDatabase() promise chain to turn the rejection into a resolved promise with some known value or error value you can detect.

这篇关于Promise all 中的同步循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆