Javascript 同步环路
我想在我的代码中做一个同步循环。 函数saveInDatabase检查数据库中是否已经存在项标题(字符串)。这就是为什么不能并行地解决它,否则该条件将永远不会应用(并将创建重复项) 我尝试将此函数封装为单独的承诺,也尝试了npm包(synchronous.js,sync),但它似乎不适合我的代码 也许这个解决方案完全是愚蠢的。 您认为用同步循环(例如foreach)取代promise.all是一个更好的主意吗?问题是我需要每次迭代的结果 我正在使用节点6.11.2。你能给我一些处理这个问题的建议吗?Javascript 同步环路,javascript,node.js,mongoose,promise,Javascript,Node.js,Mongoose,Promise,我想在我的代码中做一个同步循环。 函数saveInDatabase检查数据库中是否已经存在项标题(字符串)。这就是为什么不能并行地解决它,否则该条件将永远不会应用(并将创建重复项) 我尝试将此函数封装为单独的承诺,也尝试了npm包(synchronous.js,sync),但它似乎不适合我的代码 也许这个解决方案完全是愚蠢的。 您认为用同步循环(例如foreach)取代promise.all是一个更好的主意吗?问题是我需要每次迭代的结果 我正在使用节点6.11.2。你能给我一些处理这个问题的建议
先谢谢你 如果不使用
await
(node.js v6.11.2中没有,但会使这更简单),序列化一组返回承诺的异步操作的经典模式是使用reduce()
循环,如下所示:
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
});
Promise.all(arr.map(item => {
return saveInDatabase(item).then((myResult) => ... );
})).then(function(results) {
// all done here
}).catch(function(err) {
// error here
});
如果要保存所有结果,可以使用。然后(myResult=>…)
处理程序。将结果推入一个数组,完成后可以访问该数组
这将序列化对saveInDatabase(item)
的所有调用,它在调用第二个之前等待第一个调用完成,在调用第三个之前等待第二个调用完成,等等
如果saveInDatabase(item)
拒绝,此处的默认实现将停止。如果您想继续(您的问题中没有说明),即使它给出了一个错误,您也可以向它添加一个.catch()
,将被拒绝的承诺变成已履行的承诺
在node.js v7+中,您可以在常规的for
循环中使用wait
:
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
});
如果您可以并行运行所有请求,那么您可以这样做:
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
});
Promise.all(arr.map(item => {
return saveInDatabase(item).then((myResult) => ... );
})).then(function(results) {
// all done here
}).catch(function(err) {
// error here
});
在其中任何一种情况下,如果您不希望它在被拒绝时停止,那么在您的saveInDatabase()
承诺链中添加一个.catch()
,将拒绝转化为一个已解决的承诺,其中包含一些您可以检测到的已知值或错误值。promise.all可能是用于此作业的错误工具。您需要一次运行一个,与传递给promise.all的数组相比,用.then链表示更好<代码>[].reduce
如果您有一个数组让looper=(当前,最大值)=>{saveInDatabase(arr[current]),则可以为您设置该链;活套(0,棱长)代码>只是给你一个想法,你知道。。。无论如何,在我看来,这一切在概念上都是错误的(在本例中),请参阅。同步循环
对于异步代码来说,永远都不是解决方案。如果希望在最后一次迭代完成后访问所有结果,那么使用Promise.all并不一定是错误的。您正在使用.map
而没有从.map
回调返回任何内容,这意味着您已经在使用.map
,就好像它是.forEach
一样!谢谢你的解释。不过有件事困扰着我。如果我将所有结果放入一个数组,这将无法解决在数据库中检查是否存在任何重复项(根据其标题)的问题。我想我将修改saveInDatabase函数的用途:它只返回所有项的列表,而不是在数据库中随意“保存”。然后我可以检查最终数组中的重复条件。是的,我忘了告诉你一个项目可以返回子项目,等等。。。