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()
返回。