Javascript NodeJS:在迭代之间等待的异步循环
在将对象数组(objects[])保存到DB之前,我尝试进行一些检查(使用mongoose的mongoDB):Javascript NodeJS:在迭代之间等待的异步循环,javascript,node.js,Javascript,Node.js,在将对象数组(objects[])保存到DB之前,我尝试进行一些检查(使用mongoose的mongoDB): 这些对象已按日期排序,因此对象[0]。日期低于对象[1]。日期 每个对象都应检查上次保存的相关对象是否具有不同的值(以避免两次保存相同的信息)。这意味着我必须在每次保存之前查询数据库,以进行检查,并且必须存储这些对象中的每一个,以便能够使用正确的对象进行检查。如果对象未按顺序存储,则最后保存的相关对象可能不是正确的对象 深入解释: let testArray = [0, 1, 2,
- 这些对象已按日期排序,因此对象[0]。日期低于对象[1]。日期
- 每个对象都应检查上次保存的相关对象是否具有不同的值(以避免两次保存相同的信息)。这意味着我必须在每次保存之前查询数据库,以进行检查,并且必须存储这些对象中的每一个,以便能够使用正确的对象进行检查。如果对象未按顺序存储,则最后保存的相关对象可能不是正确的对象
let testArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
testArray.asyncForEach(function(element) {
setTimeout(() => {
console.log(element);
}, Math.random() * 500);
});
HTTP请求被发送到API。它返回一个对象数组(按日期排序),我要处理这些对象并将其保存在我的MongoDB上(使用mongoose)。我必须遍历所有这些对象,对于每个对象:
- 查找存储在DB上的前一个相关对象(可能是该数组中的一个)
- 检查“已存储”和要保存的对象之间的一些值,以评估新对象是否必须保存或可以丢弃
- 保存或放弃它,然后跳转到下一个迭代
- 数组中的项必须按顺序存储在数据库中:首先是那些日期较低的项,因为每个项都可以被稍后存储的日期较高的对象修改
- 如果下一次迭代在上一次迭代完成之前开始,则搜索上一个对象的查询无法找到它(如果它尚未存储)
let testArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
testArray.asyncForEach(function(element) {
setTimeout(() => {
console.log(element);
}, Math.random() * 500);
});
在forEach/for循环上使用promissions或async/await只能使迭代异步,但它会同时启动所有迭代
我曾尝试在forEach/for循环中使用async/await函数,甚至创建了自己的asyncfeach函数,如下所示,但这些都不起作用:
Array.prototype.asyncForEach = function(fn) {
return this.reduce(
(promise, n) => promise.then(() => fn(n)),
Promise.resolve()
);
};
测试功能:
let testArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
testArray.asyncForEach(function(element) {
setTimeout(() => {
console.log(element);
}, Math.random() * 500);
});
提供的示例应显示每种情况下订单上的数字。如果内部函数(示例中的setTimeout)应该返回一个承诺,则这不是问题
我认为我需要的是一个循环,它在迭代之间等待一些函数/承诺,并且只在第一个迭代已经完成时才开始下一个迭代
我怎么能这么做?提前谢谢你 嗯,好吧,我不能100%确定我是否正确理解了你的问题。但是,如果您尝试执行异步数组操作,等待每个项的逻辑,则可以按如下方式执行:
async loadAllUsers() {
const test = [1,2,3,4];
const users = [];
for (const index in test) {
// make some magic or transform data or something else
await users.push(test[index])
}
return users;
}
然后您可以简单地用“wait”调用这个函数。我希望这对您有所帮助。在
asyncfeach
函数中,您正在解析承诺,setTimeout
不会返回承诺。因此,如果您将setTimeout
转换为承诺。它将按预期工作。
以下是修改后的代码:
testArray.asyncForEach(function(element) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(element);
return resolve(element)
}, Math.random() * 500);
})
});
constmyarray=['a','b','c','d'];
异步函数等待(ms){//注释3
返回新承诺(resolve=>setTimeout(resolve,ms));
}
异步函数doSomething(){
等待myArray.reduce(异步(承诺,项目)=>{
等待承诺;//评论2
等待等待(1000);
//在这里,我们可以等待其他异步的东西,比如DB调用
document.getElementById('results').append(`${item}`);
},Promise.resolve());//注释1
}
设置超时(()=>doSomething(),1000)代码>
1秒后开始
Math.random()是随机的:)使用生成器函数?@Joe Math.random()用于模拟可能需要一些时间才能完成的函数finish@LeeBrindley,我会读到的,谢谢!没问题,下面的答案也是完全可以接受的。发电机功能绝对值得一读。谢谢回答!当wait(示例中的user.push)中的函数在每次迭代中花费相同的时间时,我得到了预期的结果。但是,当该函数使用可变时间(可以用setTimeout模拟,如所提供的示例中所示)时,将返回未排序的项。我认为这是因为所有for循环迭代都是同时启动的,即使每个迭代在其自身的处理过程中也是异步的。我只需要一次运行一个迭代谢谢回答!你说得对,就这么简单。我不知道为什么我在这个问题上被耽搁了这么多时间:/谢谢你的回答和解释!现在我对reduce()的功能有了一点更好的理解,可能我没有像应该的那样使用它。当然,我会努力实现你的回应,它解决了我所有的疑问,似乎是我问题的完美解决方案!