Promise与setTimeout你们应该都比较熟悉,不管是面试中仍是在实际编程它们都会常常出现。面试题中常常会将两者放在一块儿,加些console,让你判断输出顺序,这些熟悉可是又陌生的code让人抓狂,到底顺序是啥呢?js的世界里没有偶然,没有侥幸,一切发生皆有其起因,今天让咱们来一探究竟!java
很少说,直接上菜:面试
setTimeout(() => {
// t1
console.log(1);
}, 0);
// t2
console.log(2);
var promise1 = new Promise(function (resolve, reject) {
// t3
console.log(3);
resolve(4)
setTimeout(() => {
// t5
console.log(5);
});
var promise2 = Promise.resolve().then(() => {
t6
console.log(6);
});
}).then((res) => {
t4
console.log(res);
});
var promsie3 = Promise.resolve().then(() => {
// t7
console.log(7);
});
// t8
console.log(8);
复制代码
你们能够先在纸上写下答案,咱们后面会一一拆解。这是一个大综合,看着挺复杂,实际上是只纸老虎,只要咱们能掌握其关键之处,便能很轻松的写出输出顺序。ajax
首先,咱们先观察题目,发现其代码类型能够分为:setTimeout,Promise,全局下的console这三部分,再细致一点其实就是同步任务与异步任务。这类问题的关键就是同步与异步任务的处理,好,让咱们一一来分解。编程
javaScript是一门单线程语言(重点),这样js事件循环就比如像是去银行窗口窗口办理业务,得排队按顺序去办理,js事件也得按照注册顺序去执行。那万一中间某一js事件执行时间很长,那是否是得一直等待吗?固然这种状况是存在的,不过咱们有相应的处理方式:异步任务。例如咱们浏览网页时页面发起的ajax请求,就是异步任务,这样就不阻塞主页面的浏览了。让咱们用一张图来讲明这个过程:promise
1 单个异步任务bash
setTimeout(() => {
console.log('start');
}, 0);
console.log('end');
// end
// start
复制代码
这个很简单,你们应该一目了然
复制代码
2 两个相同方式的异步任务异步
setTimeout(() => {
// t2
console.log(0);
}, 0);
setTimeout(() => {
// t2
console.log(1);
}, 100);
// 0
// 1
复制代码
对于延时器来讲,执行到它时就开始计时,时间结束后将回调注册到任务队列中,因而任务队列
中的顺序是:t2,t1。因此输出便为0,1。
复制代码
setTimeout与Promise混合在一块儿的时候是什么状况呢?这里咱们将异步任务再细分一下:微任务,宏任务。函数
让咱们先来看看微任务与宏任务都有哪些:post
咱们用一张图来讲明:ui
在异步任务队列里微任务的优先级是高于宏任务的。在主线程任务结束后,会读取异步任务队列里的任务,判断微任务队列里是是否有任务,有的话执行。执行完毕后循环判断。直至为空,再执行宏任务队列,循环往复。
好,关键之处咱们已经讲解完毕,如今让咱们回头来看上面的那道‘大综合’ 让咱们逐步拆解:
好,如今咱们来整理下
好,如今咱们就能轻易的说出输出的值了:2,3,8,6,4,7,1,5。小伙伴们,大家作对了吗?
以上是我我的对整个过程的理解,在细节上或者一些过程上可能存在些误差,不是很准确,仅供参考,加深理解。同窗们若是发现有不对的地方,欢迎批评指正。