【发布时间】:2021-08-11 01:20:25
【问题描述】:
我无法理解异步代码如何在 javascript 中运行。
我有一个类似下面的代码:
const start = name => console.log(`${name} started`);
const finish = name => console.log(`${name} finished`);
const wrap = async (promise, name) => {
start(name);
const promiseResult = await promise;
finish(name);
return promiseResult;
}
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const inner = async ms => {
return await sleep(1000);
}
const outer = async ms => {
await wrap(inner(ms), 'inner1');
await wrap(inner(ms), 'inner2');
await wrap(inner(ms), 'inner3');
}
const testPromise = async promise => {
const t0 = performance.now();
const promiseResult = await promise;
const t1 = performance.now();
console.log(`Running promise took ${t1 - t0} milliseconds`);
return promiseResult;
}
testPromise(wrap(outer(5000), 'outer'));
以上代码的输出为:
inner1 started
outer started
inner1 finished
inner2 started
inner2 finished
inner3 started
inner3 finished
outer finished
Running promise took 3026.2199999997392 milliseconds
正如你在输出中看到的,inner1 是在outer 启动之前启动的,这很奇怪!我期望的是所有inner 调用都在outer 的开始和结束内开始和结束。
我在 Google 上做了很多研究,但遗憾的是找不到任何有用的东西。
对我有用的是为outer 调用显式模拟wrap 函数,如下所示:
const start = name => console.log(`${name} started`);
const finish = name => console.log(`${name} finished`);
const wrap = async (promise, name) => {
start(name);
const promiseResult = await promise;
finish(name);
return promiseResult;
}
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const inner = async ms => {
return await sleep(1000);
}
const outer = async ms => {
await wrap(inner(ms), 'inner1');
await wrap(inner(ms), 'inner2');
await wrap(inner(ms), 'inner3');
}
const testPromise = async () => {
const t0 = performance.now();
const outerName = 'outer'; // -- emulate calling `await wrap(outer(5000), 'outer')`
start(outerName); // --
const promiseResult = await outer(5000); // --
finish(outerName); // -- finished emulation of `wrap`
const t1 = performance.now();
console.log(`Running promise took ${t1 - t0} milliseconds`);
return promiseResult;
}
testPromise();
上面代码的输出是我真正期望的:
outer started
inner1 started
inner1 finished
inner2 started
inner2 finished
inner3 started
inner3 finished
outer finished
Running promise took 3155.5249999510124 milliseconds
我做错了什么导致inner1 在outer 启动之前启动?
【问题讨论】:
-
当您拥有
a(b())时,必须先解析函数调用b(),然后才能处理a()。毕竟,您需要将来自b()的值传递给a()。testPromise(wrap(outer(5000), 'outer'));也会发生同样的事情 -outerr(5000)必须被称为 first。进而调用inner。哪个记录它。之后会发生一堆暂停和取消暂停,这就是为什么你会得到outernext。 -
你运行的第一件事是外部的,它立即返回一个承诺。然后你运行 inner1 ,它也返回一个承诺,并在 1000 毫秒后解决。这将为inner1运行wrap,所以第一个输出是inner1,因为outer需要5000ms才能到达它的wrap调用
-
const inner = async ms => { return await sleep(1000); }是一种反模式。const inner = () => sleep(1000)做了完全相同的事情。在outer你写await wrap(inner(ms), 'inner1');但ms参数被忽略。也许你的意思是写await wrap(sleep(ms), "first")?wrap返回一个结果,但你没有将它分配给任何东西?
标签: javascript async-await promise