Javascript嵌套异步调用执行顺序

Javascript嵌套异步调用执行顺序,javascript,async-await,promise,Javascript,Async Await,Promise,我很难理解异步代码如何在javascript中运行 我有一个类似于以下的代码: const start=name=>console.log(`${name}start`); const finish=name=>console.log(`${name}finished`); const wrap=async(承诺,名称)=>{ 开始(姓名); const promiseResult=等待承诺; 完成(名称); 回报承诺; } const sleep=ms=>newpromise(resolve

我很难理解异步代码如何在javascript中运行

我有一个类似于以下的代码:

const start=name=>console.log(`${name}start`);
const finish=name=>console.log(`${name}finished`);
const wrap=async(承诺,名称)=>{
开始(姓名);
const promiseResult=等待承诺;
完成(名称);
回报承诺;
}
const sleep=ms=>newpromise(resolve=>setTimeout(resolve,ms));
常量内部=异步ms=>{
返回等待睡眠(1000);
}
常量外部=异步ms=>{
等待包装(内部(ms),“内部1”);
等待包装(内部(ms),“内部2”);
等待包装(内部(ms),“内部3”);
}
const testPromise=异步承诺=>{
const t0=性能。现在();
const promiseResult=等待承诺;
常数t1=性能。现在();
log(`Running promise花费了${t1-t0}毫秒`);
回报承诺;
}

testPromise(包装(外部(5000),“外部”)根据我对异步JS的理解,与同步代码相反,所有代码都同时运行


发生这种情况的唯一原因是inner1的执行速度比outer快。

经过多次尝试,我发现异步函数同步运行,直到它们到达wait或return

第一个代码中发生的行为可以解释为:

与任何函数调用一样,首先计算函数参数,然后再计算函数本身,调用
wrap(outer(5000),“outer”)
将首先计算
outer(5000)
函数调用。在计算
outer
调用,尤其是第一行
wrap(internal(ms),'inner1')
时,同样的情况也会发生,
internal(ms)
将首先在这些嵌套调用中注册第一个承诺,这些嵌套调用将由
wrap
函数包装(这是对
wrap
函数的第一个调用),由于
wrap(internal(ms),'inner1')
outer
函数中的第一个异步调用(first
await
语句),因此它将被同步计算,之后所有其他
await
语句将注册依赖于第一个承诺
await(internal(ms)'inner1')
,然后,
outer
函数将被
wrap
包装。这就是为什么首先启动
inner1
,然后启动
outer
,然后其他所有操作都按预期运行的原因

我找到的解决方案是传递一个回调,该回调将承诺返回给
wrap
函数,而不是立即传递承诺

const start=name=>console.log(`${name}start`);
const finish=name=>console.log(`${name}finished`);
const wrap=async(promiseCallback,name)=>{
开始(姓名);
const promiseResult=等待promiseCallback();
完成(名称);
回报承诺;
}
const sleep=ms=>newpromise(resolve=>setTimeout(resolve,ms));
常量内部=异步ms=>{
返回等待睡眠(1000);
}
常量外部=异步ms=>{
等待换行(()=>inner(ms),'inner1');
等待换行(()=>inner(ms),'inner2');
等待换行(()=>inner(ms),'inner3');
}
const testPromise=async promiseCallback=>{
const t0=性能。现在();
const promiseResult=等待promiseCallback();
常数t1=性能。现在();
log(`Running promise花费了${t1-t0}毫秒`);
回报承诺;
}

testPromise(()=>wrap(()=>outer(5000),“outer”)您的问题表明了对有效使用
async
wait
的一些误解-

const sleep=ms=>
新承诺(r=>setTimeout(r,ms))
异步函数包装(p,标签){
日志(“已启动”,标签)
const t=Date.now()
常数结果=等待p
console.log(“完成”,标签)
返回{result,delta:Date.now()-t}
}
异步函数内部(){
等待睡眠(1000)
返回Math.floor(Math.random()*100)
}
异步函数外部(){
常量a=等待换行(内部(),“内部1”)
常量b=等待换行(内部(),“内部2”)
常量c=等待换行(内部(),“内部3”)
返回[a、b、c]
}
包裹(外部(),“外部”)
.then(JSON.stringify)

.then(console.log,console.error)
Async并不意味着并发。异步执行在JS中仍然是顺序的。除非有例外,但这不是任何例外。好的,明白了。谢谢你的更正。我还不太了解这一点。当您有
a(b())
时,必须先解决函数调用
b()
,然后才能处理
a()
。毕竟,您需要将
b()
中的值传递给
a()
。同样的事情也发生在testPromise(wrap(outer(5000),'outer')-
outerr(5000)
必须首先调用。依次调用
内部
。它记录了它。之后会发生一系列暂停和取消暂停,这就是为什么接下来会得到
outer
。运行的第一件事是outer,它会立即返回一个承诺。然后运行inner1,它也会返回一个承诺,1000毫秒后,它会解析。这将为inner1运行wrap,因此第一个输出是inner1,因为outer需要5000ms才能到达其wrap调用
const-inner=async-ms=>{return-await-sleep(1000);}
是一种反模式<代码>常量内部=()=>睡眠(1000)
做完全相同的事情。在
outer
中编写
wait wrap(内部(ms),'inner1')
但忽略
ms
参数。也许你的意思是写
等待包装(sleep(ms),“first”)
wrap
返回一个结果,但您没有将其分配给任何对象?“我发现异步函数一直同步运行,直到在它们中的第一个wait调用之后。”非常小的更正:异步函数一直同步运行,直到它们到达
wait
return
。在那一点上,他们就来了