async/await
使用 async
关键字可以让函数具有异步特征,但总体上其代码仍然是同步求值的。
async function foo() {
console.log(1);
}
foo();
console.log(2);
异步函数如果使用 return
关键字返回了值(如果没有 return
则会返回 undefined
),这个值会被 Promise.resolve()
包装成一个Promise
对象。
注:异步函数始终返回Promise
对象!!
async function foo() {
console.log(1);
return 3;
}
// 给返回的Promise添加一个解决处理程序
foo().then(console.log);
console.log(2);
// 1
// 2
// 3
//等同于
async function foo() {
console.log(1);
return Promise.resolve(3);
}
// 给返回的Promise添加一个解决处理程序
foo().then(console.log);
console.log(2);
// 1
// 2
// 3
await
async
函数返回一个 Promise
对象,可以使用 then
方法添加回调函数。当函数执行的时候,一旦遇到 await
就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
await
关键字会暂停执行异步函数之后的代码,使其让出 JavaScript
运行时的执行线程,先执行异步。
-
async
单独使用的时候,放在函数前面表示这个函数是一个异步函数,如果async
函数有返回结果,必须要用.then()
方法来承接(也就是返回的值会被自动处理成promise
对象)async function helloAsync(){ return "helloAsync"; } console.log(helloAsync()) // Promise {<resolved>: "helloAsync"} helloAsync().then(v=>{ console.log(v); // helloAsync })
-
async await
搭配使用的时候,await
是等待此函数执行后,再执行下一个,可以把异步函数变成同步来执行,控制函数的执行顺序。-
当
await
后跟的函数是返回的promise
let foo = () => { return new Promise(resolve => { setTimeout(() => { console.log('lee'); resolve(); }, 1000); }); }; async function bar() { await foo(); console.log('van'); } console.log(bar()); // 隔1秒同时输出 lee van
-
当
await
后跟的是普通函数(非promise()
)let f1 = () => { setTimeout(() => { console.log('lee'); }, 1000); }; let f2 = () => { setTimeout(() => { console.log('van'); }, 1000); }; async function bar() { await f1(); await f2(); console.log('yeah'); } console.log(bar()); // yeah 隔1秒同时输出 lee fan
-
- 如果它等到的是一个
Promise
对象,await
就忙起来了,它会阻塞后面的代码,等着Promise
对象resolve
,然后得到resolve
的值,作为await
表达式的运算结果。 - 如果它等到的不是一个
Promise
对象,那await
表达式的运算结果就是它等到的东西;
await
一定要搭配async
使用,如果在async function
函数体外使用await
,你只会得到一个语法错误。
注意:
await
关键字必须在异步函数中使用,不能在顶级上下文如<script>
标签或模块中使用await
关键字也只能直接出现在异步函数的定义中,在同步函数内部使用await
会抛出SyntaxError
await
不允许出现在箭头函数中- 异步函数如果不包含
await
关键字,其执行基本上跟普通函数没有什么区别 JavaScript
运行时在碰到await
关键字时,会记录在哪里暂停执行。等到await
右边的值可用了,JavaScript
运行时会向消息队列中推送一个任务,这个任务会恢复异步函数的执行
实例分析await
执行顺序:
async function foo() {
console.log(2);
console.log(await Promise.resolve(8));
console.log(9);
}
async function bar() {
console.log(4);
console.log(await 6);
console.log(7);
}
console.log(1);
foo();
console.log(3);
bar();
console.log(5);
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
- 打印 1;
- 调用异步函数
foo()
; - (在
foo()
中)打印 2; - (在
foo()
中)await
关键字暂停执行,向消息队列中添加一个Promise
在落定之后执行的任务; Promise
立即落定,把给await
提供值的任务添加到消息队列;foo()
退出;- 打印 3;
- 调用异步函数
bar()
; - (在
bar()
中)打印 4; - (在
bar()
中)await
关键字暂停执行,为立即可用的值 6 向消息队列中添加一个任务; bar()
退出;- 打印 5;
- 顶级线程执行完毕;
- JavaScript 运行时从消息队列中取出解决
await
Promise
的处理程序,并将解决的值 8 提供给它; - JavaScript 运行时向消息队列中添加一个恢复执行
foo()
函数的任务; - JavaScript 运行时从消息队列中取出恢复执行
bar()
的任务及值 6; - (在
bar()
中)恢复执行,await
取得值 6; - (在
bar()
中)打印 6; - (在
bar()
中)打印 7; bar()
返回;- 异步任务完成,JavaScript 从消息队列中取出恢复执行
foo()
的任务及值 8; - (在
foo()
中)打印 8; - (在
foo()
中)打印 9; foo()
返回。