Here is how I understand things currently:
async/await in a for-loop should pause execution until the promise resolves, meaning that the next iteration of the loop won't occur until that line finishes.
Consider the following array:
const data = [];
for (let i = 0; i <= 100000; i++) {
data.push(i);
}
Method 1: Awaiting Promises in a for-loop
async function method1() {
const startTime = new Date();
console.log('start:', startTime);
for (const item in data) {
await new Promise(resolve => {
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
});
}
const endTime = new Date();
console.log('finish:', endTime);
console.log('total time:', endTime-startTime);
}
Because it requires sequential execution of promises to continue through the loop, I figured using Promise.all would be a performance enhancement that leverages asynchronous processing to a greater degree:
Method 2: Promise.all following a for-loop
async function method2() {
const promises = [];
const startTime = new Date();
console.log('start:', startTime);
for (const item in data) {
const promise = new Promise(resolve => {
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
});
promises.push(promise);
}
await Promise.all(promises);
const endTime = new Date();
console.log('finish:', endTime);
console.log('total time:', endTime-startTime);
}
My reasoning: the loop would continue to bang out new Promises while each previously created Promise attempts resolve. So in my head, method 1 = blocking... while method 2 = less blocking.
When I run these both on repl.it, I found that method method 1 is actually quicker, almost by a factor of 2. Can somebody explain why this is? Shouldn't it be the other way around?
Here is how I understand things currently:
async/await in a for-loop should pause execution until the promise resolves, meaning that the next iteration of the loop won't occur until that line finishes.
Consider the following array:
const data = [];
for (let i = 0; i <= 100000; i++) {
data.push(i);
}
Method 1: Awaiting Promises in a for-loop
async function method1() {
const startTime = new Date();
console.log('start:', startTime);
for (const item in data) {
await new Promise(resolve => {
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
});
}
const endTime = new Date();
console.log('finish:', endTime);
console.log('total time:', endTime-startTime);
}
Because it requires sequential execution of promises to continue through the loop, I figured using Promise.all would be a performance enhancement that leverages asynchronous processing to a greater degree:
Method 2: Promise.all following a for-loop
async function method2() {
const promises = [];
const startTime = new Date();
console.log('start:', startTime);
for (const item in data) {
const promise = new Promise(resolve => {
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
});
promises.push(promise);
}
await Promise.all(promises);
const endTime = new Date();
console.log('finish:', endTime);
console.log('total time:', endTime-startTime);
}
My reasoning: the loop would continue to bang out new Promises while each previously created Promise attempts resolve. So in my head, method 1 = blocking... while method 2 = less blocking.
When I run these both on repl.it, I found that method method 1 is actually quicker, almost by a factor of 2. Can somebody explain why this is? Shouldn't it be the other way around?
Share Improve this question edited Jun 5, 2020 at 17:02 stoneb asked Jun 5, 2020 at 16:56 stonebstoneb 531 silver badge5 bronze badges 1-
1
The conceptual difference between the two approaches is that one runs the asynchronous operations in parallel, the other runs them in serial. With fake asynchronous operations, you can't see the real effect of that difference. With real asynchronous operations, the effect would be obvious and running in parallel would have a way faster end-to-end time. If each asynchronous operation took
200ms
to resolve, then method 1 would resolve in~n * 200ms
and method 2 would resolve in~200ms
where n is the number of async operations you run. – jfriend00 Commented Jun 5, 2020 at 17:52
2 Answers
Reset to default 3My guess is that you resolve too fast, so the looping dominates the execution time, since method2 has two loops: one to push to the array and one for promise.all
to plete while method1 only has one loop, so your feeling "almost a factor of two" is actually theoretically correct.
Try faking an actual async operation
like new Promise(resolve => setTimeout(resolve, 200))
and you should get what you expected
To add further to what Drake said. The only reason why method 2 is slower without timeouts is because of the number of loops it will have to encounter, but in a real scenario where request or asynchronous operations have delays. Method 2 will most of the time be faster
Here is the modified snippet with SetTimeout.
const data = [];
for (let i = 0; i <= 1000; i++) {
data.push(i);
}
async function method1() {
const startTime = new Date();
console.log('start 1:', startTime);
for (const item in data) {
await new Promise(resolve => {
setTimeout(()=>{
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
},1)
});
}
const endTime = new Date();
console.log('finish 1:', endTime);
console.log('total time:', endTime-startTime);
}
async function method2() {
const promises = [];
const startTime = new Date();
console.log('start 2:', startTime);
for (const item in data) {
const promise = new Promise(resolve => {
setTimeout(()=>{
if (item % 3 === 0) {
resolve({});
} else {
resolve(item)
}
},1)
});
promises.push(promise);
}
await Promise.all(promises);
const endTime = new Date();
console.log('finish 2:', endTime);
console.log('total time:', endTime-startTime);
}
method1()
method2()
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744142967a4560288.html
评论列表(0条)