Javascript嵌套异步调用执行顺序
我很难理解异步代码如何在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
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
函数中的第一个异步调用(firstawait
语句),因此它将被同步计算,之后所有其他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
。在那一点上,他们就来了