鉴于我在命令行中使用node fileName.js
运行的以下代码,它似乎在循环中运行 all 项目,然后在最后睡眠......有点像是全部并行运行。
我希望代码在setTimeout
期间阻止/暂停,而不是仅在setTimeout完成后运行该函数。或者,如果setTimeout
不正确,则使用不同的方法,在此用例中。
const removeUsers = async () => {
const users = await db.getUsers(); // returns 32 users.
// Split the users up into an array, with 2 users in each 'slot'.
var arrays = [], size = 2;
while (users.length > 0) {
arrays.push(users.splice(0, size));
}
// Now, for each slot, delete the 2 users then pause for 1 sec.
arrays.forEach(a => {
console.log(++counter;);
// Delete 2x users.
a.forEach(async u => {
console.log('Deleting User: ' + u.id);
await 3rdPartyApi.deleteUser({id: u.id});
});
// Now pause for a second.
// Why? 3rd party api has a 2 hits/sec rate throttling.
setTimeout(function () { console.log('Sleeping for 1 sec'); }, 1000);
});
}
并且日志是这样的..
1.
Deleting User: 1
Deleting User: 2
2.
Deleting User: 3
Deleting User: 4
3.
...
(sleep for 1 sec)
(sleep for 1 sec)
(sleep for 1 sec)
...
end.
看看睡眠是不是感觉它会阻塞..它只是触发一个睡眠命令,然后在一秒钟后处理......
这就是我真正追求的......
1.
Deleting User: 1
Deleting User: 2
(sleep for 1 sec)
2.
Deleting User: 3
Deleting User: 4
(sleep for 1 sec).
3.
...
end.
答案 0 :(得分:1)
这会调用一堆async
函数。它们各自返回一个promise(async
函数总是返回promises),并且这些promise将被丢弃,因为Array#forEach
对它传递的函数的返回值没有任何作用。
a.forEach(async u => {
console.log('Deleting User: ' + u.id);
await 3rdPartyApi.deleteUser({id: u.id});
});
这启动了一个计时器,甚至没有尝试等待它。
setTimeout(function () { console.log('Sleeping for 1 sec'); }, 1000);
将计时器拆分为一个函数,该函数返回在适当的时间内解析的promise(如果您使用的是Bluebird,则可以Promise.delay
使用):
const delay = ms =>
new Promise(resolve => {
setTimeout(resolve, ms);
});
并将所有内容保存在一个async
函数中,这样您就不会丢弃任何承诺:
function* chunk(array, size) {
for (let i = 0; i < array.length;) {
yield array.slice(i, i += size);
}
}
const removeUsers = async () => {
const users = await db.getUsers(); // returns 32 users.
for (const a of chunk(users, 2)) {
console.log(++counter);
// Delete 2x users.
for (const u of a) {
console.log('Deleting User: ' + u.id);
await ThirdPartyApi.deleteUser({id: u.id});
}
console.log('Sleeping for 1 sec');
await delay(1000);
}
};