在将一组对象(objects [])保存到数据库(使用mongoose的mongoDB)之前,我正在尝试进行一些检查:
深入的解释:
HTTP请求发送到API。它返回我要处理的对象数组(按日期排序),并保存在Mongo DB中(使用mongoose)。我必须遍历所有这些对象,对于每个对象:
等待每次迭代完成很重要,因为:
已尝试:
在forEach / for循环上使用promise或async / await只会使该迭代异步,但会保持一次启动所有迭代。
我尝试在forEach / for循环中使用async / await函数,甚至创建了自己的asyncForEach函数(如下所示),但是这些都没有起作用:
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)应该返回promise没问题。
我认为我需要的是一个循环,该循环在迭代之间等待一些功能/承诺,并且仅在第一个迭代已经完成时才开始下一个迭代。
我该怎么做?预先谢谢你!
答案 0 :(得分:3)
const myArray = ['a','b','c','d'];
async function wait(ms) { // comment 3
return new Promise(resolve => setTimeout(resolve, ms));
}
async function doSomething() {
await myArray.reduce(async (promise, item) => {
await promise; // comment 2
await wait(1000);
// here we could await something else that is async like DB call
document.getElementById('results').append(`${item} `);
}, Promise.resolve()); // comment 1
}
setTimeout(() => doSomething(), 1000);
<div id="results">Starting in 1 second <br/></div>
您也可以使用已经说过的reduce
和async await
。
基本上,如果您了解reduce的工作原理,您会看到它接受2个参数,第一个是对每个步骤执行的回调,第二个是可选的初始值。
在回调中,我们的第一个参数是累加器,这意味着它接受上一步返回的内容或第一步的可选初始值。
1)您正在提供承诺解决方案的初始价值,以便您开始第一步。
2)由于这个await promise
,您将永远不会进行下一步,直到上一步完成为止,因为这是上一步的累加器值,这是有保证的,因为我们说回调是async
。我们在这里并没有解决每个人说的诺言,但是一旦上一步完成,我们将隐式解决它,然后继续下一步。
3)您可以放置await wait(30)
例如,以确保您正在限制Ajax请求并且没有发送太多请求给第三方API,因为那样的话您发送的消息数不会超过1000 /即使您的代码在计算机上执行得非常快,每秒也可以处理30个请求。
答案 1 :(得分:1)
嗯,好的,我不确定我是否以正确的方式理解了您的问题。但是,如果您尝试执行等待每个项目逻辑的异步数组操作,则可以执行以下操作:
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;
}
然后,您可以使用“ await”简单地调用此函数。希望对您有所帮助。
答案 2 :(得分:1)
在asyncForEach
函数中您要解决一个Promise,setTimeout
不会返回Promise。因此,如果您将setTimeout
转换为Promise。它将按预期工作。
这是修改后的代码:
testArray.asyncForEach(function(element) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(element);
return resolve(element)
}, Math.random() * 500);
})
});