异步概念
对于 js 不知道异步是什么,为什么需要有异步的同学来说,可以先看看我的这篇文章 如错误之处,请求指点,谢谢阅读。
异步进一步理解
对于已经了解了异步的基本概念的同学,我们可以来看一下,下面的这个例子,有助于我们更好的理解异步(注意chrom: 版本:72.0.3626.121 版本不同结果有点差异)
复制代码
// 今日头条面试题
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('settimeout')
})
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
// result:
// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// settimeout
复制代码
执行过程的分析:
- 遇到 console.log('script start'), 放在主线程中立即执行,所以第一步先输出 script start
- 遇到 setTimeout,因为 setTimeout 是异步的,所以将回调函数放入异步队列中去等待,等待主线程中的任务执行完之后,再通过事件轮询的方式去调用
- 遇到 async1 函数的调用,此时走到 async1 函数里面输出 async1 start
- 遇到 await 关键字,进入到 async2 函数中输出 async2,将 await 后面的代码放入微任务中,执行后面的操作
- 遇到 Promise 直接输出promise1,将回调函数放入微任务中,执行后面的操作
- 遇到 console.log('script end'), 放在主线程中立即执行,所以第一步先输出 script end,到这个时候主线程中的代码就执行完了
- 主线程中的代码执行完之后,立即执行所有的微任务。分别输出 async1 end,promise2
- 最后通过事件轮询的方式将异步队列中代码,拿到主线程中来执行 (输出 settimeout)
- 重复步骤8
注意
- await 关键字必须在用 async 关键字修饰的函数中才能使用。
- async 语法其实也就是 Promise 语法。
上面例子中的这部分代码可以转化为:
转化前:
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
复制代码
转化后:
async function async1() {
console.log('async1 start')
new Promise((resolve, reject) => {
this.async2()
resolve()
})
.then(body => {
console.log('async1 end')
})
}
复制代码
为了巩固大家可以练下下面两个题目:
async function async1() {
console.log('async1 start');
await async2();
setTimeout(function() {
console.log('setTimeout1')
},0)
}
async function async2() {
setTimeout(function() {
console.log('setTimeout2')
},0)
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout3');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
复制代码
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
new Promise((resolve, reject) => {
console.log('promise3')
resolve()
})
.then(body => {
console.log('promise4')
})
}
console.log('script start')
setTimeout(function () {
console.log('settimeout')
})
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
复制代码
答案:
script start
async1 start
promise1
script end
promise2
setTimeout3
setTimeout2
setTimeout1
复制代码
script start
async1 start
async2
promise3
promise1
script end
promise4
async1 end
promise2
settimeout
复制代码
谢谢大家的阅读,不对之处,请指教。