虽然大家知道 async/await, 但是很多人对这个方法中内部怎么执行的还不是很了解, 本文是我看了一遍技术博客理解 JavaScript 的 async/await(如果对 async/await 不熟悉可以先看下 http://es6.ruanyifeng.com/#docs/async)后拓展了一下, 我理了一下 await 之后 JS 的执行顺序, 希望可以给别人解疑答惑, 先简单介绍一下 async/await.
async/await 是一种编写异步代码的新方法. 之前异步代码的方案是回调和 promise.
async/await 是建立在 promise 的基础上.
async/await 像 promise 一样, 也是非阻塞的.
async/await 让异步代码看起来, 表现起来更像同步代码. 这正是其威力所在.
async 怎么处理返回值
- async function testAsync() {
- return "hello async";
- }
- let result = testAsync();
- console.log(result)
- // 输出结果: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello async"
从结果中可以看到 async 函数返回的是一个 promise 对象, 如果在函数中 return 一个直接量, async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象.
如果 asyn 函数没有返回值
- async function testAsync1() {
- console.log("hello async");
- }
- let result1 = testAsync1();
- console.log(result1);
- // 结果: hello async
- Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
结果返回 Promise.resolve(undefined).
await 做了什么处理
从字面意思上看 await 就是等待, await 等待的是一个表达式, 这个表达式的返回值可以是一个 promise 对象也可以是其他值.
很多人以为 await 会一直等待之后的表达式执行完之后才会继续执行后面的代码, 实际上 await 是一个让出线程的标志. await 后面的函数会先执行一遍, 然后就会跳出整个 async 函数来执行后面 JS 栈 (后面会详述) 的代码. 等本轮事件循环执行完了之后又会跳回到 async 函数中等待 await
后面表达式的返回值, 如果返回值为非 promise 则继续执行 async 函数后面的代码, 否则将返回的 promise 放入 promise 队列(Promise 的 Job Queue)
async/await 执行顺序
先看一个例子
- function testSometing() {
- console.log("执行 testSometing");
- return "testSometing";
- }
- async function testAsync() {
- console.log("执行 testAsync");
- return Promise.resolve("hello async");
- }
- async function test() {
- console.log("test start...");
- const v1 = await testSometing();// 关键点 1
- console.log(v1);
- const v2 = await testAsync();
- console.log(v2);
- console.log(v1, v2);
- }
- test();
- var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});// 关键点 2
- promise.then((val)=> console.log(val));
- console.log("test end...")
输出结果:
test start...
执行 testSometing
- promise start..
- test end...
- testSometing
执行 testAsync
- promise
- hello async
- testSometing hello async
当 test 函数执行到
const v1 = await testSometing();
的时候, 会先执行 testSometing 这个函数打印出 "执行 testSometing" 的字符串, 然后因为 await 会让出线程就会区执行后面的
- var promise = new Promise((resolve)=> {
- console.log("promise
- start.."); resolve("promise");
- });// 关键点 2
然后打印出 "promise start.." 接下来会把返回的这 promise 放入 promise 队列(Promise 的 Job Queue), 继续执行打印 "test end...", 等本轮事件循环执行结束后, 又会跳回到 async 函数中(test 函数), 等待之前 await 后面表达式的返回值, 因为 testSometing 不是 async 函数, 所以返回的是一个字符串 "testSometing",test 函数继续执行, 执行到
const v2 = await testAsync();
和之前一样又会跳出 test 函数, 执行后续代码, 此时事件循环就到了 promise 的队列, 执行 promise.then((val)=> console.log(val));then 后面的语句, 之后和前面一样又跳回到 test 函数继续执行.
这个就是在 async/await 函数之后 JS 的执行顺序, 我们再看一个列子把 testSometing 函数前面加上 async
- async function testSometing() {
- console.log("执行 testSometing");
- return "testSometing";
- }
- async function testAsync() {
- console.log("执行 testAsync");
- return Promise.resolve("hello async");
- }
- async function test() {
- console.log("test start...");
- const v1 = await testSometing();
- console.log(v1);
- const v2 = await testAsync();
- console.log(v2);
- console.log(v1, v2);
- }
- test();
- var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//3
- promise.then((val)=> console.log(val));
- console.log("test end...")
输出结果:
test start...
执行 testSometing
- promise start..
- test end...
- promise
- testSometing
执行 testAsync
- hello async
- testSometing hello async
和上一个例子比较发现 promise.then((val)=> console.log(val)); 先与 console.log(v1); 执行了, 原因是因为现在 testSometing 函数加了 async, 返回的是一个 Promise 对象要要等它 resolve, 所以将当前 Promise 推入队列, 所以会继续跳出 test 函数执行后续代码. 之后就开始执行 promise 的任务队列了, 所 / 以先执行了 promise.then((val)=> console.log(val)); 因为这个 Promise 对象先推入队列;
总结
写到这里大家应该已经清楚了使用 async/await 进行异步操作时 JS 的执行顺序. 如果大家对有什么意见或建议可以指出, 希望大家不吝赐教.
来源: https://www.cnblogs.com/liutianzeng/p/10975343.html