这是我参与「第四届青训营 」笔记创作活动的第4天,今天学习了JS里面的异步操作之async/await。
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后跟的函数是返回的promiselet 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会抛出SyntaxErrorawait不允许出现在箭头函数中- 异步函数如果不包含
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 运行时从消息队列中取出解决
awaitPromise的处理程序,并将解决的值 8 提供给它; - JavaScript 运行时向消息队列中添加一个恢复执行
foo()函数的任务; - JavaScript 运行时从消息队列中取出恢复执行
bar()的任务及值 6; - (在
bar()中)恢复执行,await取得值 6; - (在
bar()中)打印 6; - (在
bar()中)打印 7; bar()返回;- 异步任务完成,JavaScript 从消息队列中取出恢复执行
foo()的任务及值 8; - (在
foo()中)打印 8; - (在
foo()中)打印 9; foo()返回。