异步/等待理解JavaScript

什么是

名字怎么写

异步和等待执行?
任何名称都是有意义的,应该先按字面意思取Async是“asynchronous”的缩写,wait可以被认为是“async wait”的缩写因此,应该很好地理解,async用于声明函数是异步的,而away用于等待异步方法完成执行。

还有一个有趣的语法规则,wait只能出现在异步函数中那么一个细心的朋友会有一个问题,如果等待只能出现在异步函数中,这个异步函数应该如何调用呢?

如果您需要等待调用一个异步函数,那么您必须在这个调用之外包装另一个异步函数,然后...进入一个死循环,永远不会有早一天...

如果异步函数不需要等待调用,异步扮演什么角色?

异步做什么
这个问题的关键是异步函数如何处理它的返回值!

我们当然希望它可以通过return语句直接返回我们想要的值,但是如果是这样的话,似乎就没有等待了因此,编写一个代码来尝试看看它会返回什么:

异步函数testasync () {
返回“hello async”;< br>}
常量结果=测试同步();
控制台.日志(结果);< br>

看到输出,突然意识到这是一个承诺对象

c:\ var \ test node-harmony _ async _ away。
承诺{'hello async'}
因此,异步函数返回一个承诺对象该信息也可以从文档中获得。异步函数(包括函数语句、函数表达式、Lambda表达式)将返回一个Promise对象。如果函数中返回了直接数量,异步将通过Promise.resolve()将直接数量封装到Promise对象中

async函数返回一个Promise对象,所以如果最外层不能使用wait来获得它的返回值,当然我们应该使用原始的方法:then()链来处理Promise对象,就像这个

testasync()。然后(v = {
控制台. log(v));//输出hello async
});< br>

现在回头想想,如果异步函数不返回值呢?很容易想象它会返回承诺。解决(未定义)

调用了承诺-无等待的特性,因此如果异步函数在没有等待的情况下执行,它将立即执行,返回一个承诺对象,并且永远不会阻塞下面的语句。这与返回承诺对象的普通函数没有什么不同。

,那么下一个关键点是wait关键字

等待到底是什么?一般来说,away被认为是在等待异步功能完成但是,根据语法,wait是在等待一个计算结果为承诺对象或其他值的表达式(换句话说,没有特殊限制)

因为异步函数返回一个Promise对象,所以wait可以用来等待异步函数的返回值——也可以说wait正在等待异步函数,但是应该清楚它所等待的实际上是一个返回值请注意,wait不仅用于等待承诺对象,它还可以等待任何表达式的结果,因此wait后面实际上可以跟普通函数调用或直接数量。因此,下面的例子可以完全运行

函数get some(){
返回' some ';< br>}
异步函数testAsync() {
返回承诺.解析(“hello async”);< br>}
异步功能测试(){
常量v1 =等待GetSource();
常量v2 =等待测试同步();
控制台. log(v1,v2);< br>}
测试()。
|等待它想要等待的东西,然后
离开等待它想要等待的东西,承诺对象或其他值,然后?我首先要说的是,wait是一个运算符,用于构成一个表达式。等待表达式的结果取决于类似的东西。

如果它不等待承诺对象,那么等待表达式的结果就是它所等待的

如果它在等待承诺对象,等待将会很忙。它将阻塞下面的代码,等待承诺对象解析,然后获得解析值作为等待表达式的计算结果

被上面的字挡住了...请放心,这就是为什么必须在异步函数中使用wait异步函数调用不会导致阻塞;它内部的所有阻塞都封装在一个承诺对象中,并异步执行

async/away为我们
做了什么来进行简单的比较
上面已经解释了async将它的函数返回值(函数表达式或Lambda)打包到一个Promise对象中,away将等待Promise完成并返回它的解析结果例如,

现在使用setTimeout来模拟耗时的异步操作。首先,让我们看看

函数如何花费很长时间(){
返回新承诺(resolve = {
settimeout(()= resolve(' long _ time _ value '),1000)在没有异步/等待的情况下编写。
});< br>}
耗时()。然后(v = {
控制台. log(' get ',v);
});
如果使用async/wait,它将像这样
函数需要很长时间(){
returnnewpromise(resolve = {
settime out(()= resolve(' long _ time _ value '),1000);
});< br>}
异步功能测试(){
常量v =等待TakeLongTime();控制台日志(v);< br>}
测试()。< br>

位目光敏锐的同学发现takeLongTime()没有被声明为异步事实上,takeLongTime()本身就是返回的承诺对象,无论有没有异步,结果都是一样的。如果你不明白,请回去看看上面的“异步是做什么的?”

的另一个问题出现了。这两种代码在处理异步调用(实际上,处理承诺对象)方面的区别并不明显。即使使用异步/等待也需要编写更多的代码。它有什么优点?

异步/等待的优势在于,在处理当时的链
单个承诺链时,无法找到异步/等待的优势。然而,如果需要处理由多个承诺组成的当时链,优势就可以体现出来(有趣的是,承诺通过当时链解决了多层回调的问题,现在使用异步/等待来进一步优化它)

假设一个服务在多个步骤中完成,每个步骤都是异步的,并且取决于前一步的结果我们仍然使用setTimeout来模拟异步操作:

/**
*传入参数n,它指示该函数的执行时间(毫秒)< br> *并且执行的结果是n 200。此值将用于下一步
*/
功能需要很长时间(n) {
返回新承诺(resolve = {
set time out(()= resolve(n200),n);
});< br>}
功能步骤1(n) {
控制台. log(` step 1 with $ { n } `);
返回需要很长时间(n);< br>}
功能步骤2(n) {
控制台. log(` step 2 with $ { n } `);
返回需要很长时间(n);< br>}
功能步骤3(n) {
控制台.日志(`步骤3含$ { n } `);
返回需要很长时间(n);< br>}

现在使用承诺来实现这三个步骤的处理

functiondoit () {
控制台时间(“doit”);
常量时间1 = 300;
步骤1(时间1)
。然后(时间2 =步骤2(时间2))
。然后(时间3 =步骤3(时间3))
。然后(result = {
console . log(` result is $ { result } `);
控制台.时间结束(“DoIt”);
});
}
DoIT();
//c:\ var \ Testnode-harmony _ async _ away。
//step 1 with 300
//step 2 with 500
//step3 with 700
//results 900
//doit:1507.251m

输出结果结果是step 3的参数700 200 = 900()DoIt()依次执行了三个步骤,总共花费了300,500,700 = 1500毫秒,这与console.time()/console.timeEnd()计算的结果一致如果用async/wait实现

,则它将是

async函数doit () {
控制台时间(“doit”);
常量时间1 = 300;
常量时间2 =等待步骤1(时间1);
常量时间3 =等待步骤2(时间2);
常量结果=等待步骤3(时间3);
console . log(` result is $ { result } `);
控制台.时间结束(“DoIt”);
}
DoIT();< br>

结果与之前的承诺实现相同,但是该代码看起来是否更清晰,几乎与同步代码

相同,甚至更酷
现在,更改业务需求仍然是一个三步过程,但是每一步都需要前一步的结果

函数step 1(n){
console . log(` step 1 with $ { n } `);
返回需要很长时间(n);< br>}
功能步骤2(m,n) {
控制台. log(`步骤2,带${m}和$ { n } `);
回程耗时(m n);< br>}
功能步骤3(k,m,n) {
控制台. log(`步骤3含${k}、${m}和$ { n } `);
返回需要很长时间(k m n);< br>}
这一次,使用异步/等待写入:
异步函数doit () {
控制台. time(' doit ');
常量时间1 = 300;
常量时间2 =等待步骤1(时间1);
常量时间3 =等待步骤2(时间1,时间2);
常量结果=等待步骤3(时间1,时间2,时间3);
console . log(` result is $ { result } `);
控制台.时间结束(“DoIt”);
}
DoIT();
//c:\ var \ test node-harmony _ async _ wait。
//step 1 with 300
//step 2 with 800 = 300 500
//step 3 with 1800 = 300 500 1000
//结果是2000
//DoIt:2907.387 ms

似乎与前面的示例没有什么不同,只是执行时间较长!别担心,仔细想想如果它被写成一个承诺会是什么样子。

功能doIt() {
控制台时间(“DoIt”);
常量时间1 = 300;
步骤1(时间1)
。然后(时间2 = {
返回步骤2(时间1,时间2)
。然后(时间3 =

名字怎么写



|


[此内容通过骑士价值品牌展馆的许可发布]

大家都在看

相关专题