赞
踩
event loop
它的执行顺序:
Web Worker
任务,有则执行微任务包括:MutationObserver
、Promise.then()或catch()
、Promise为基础开发的其它技术,比如fetch API
、V8
的垃圾回收过程、Node独有的process.nextTick
。
宏任务包括:script
、setTimeout
、setInterval
、setImmediate
、I/O
、UI rendering
。
注意⚠️:在所有任务开始的时候,由于宏任务中包括了script
,所以浏览器会先执行一个宏任务,在这个过程中你看到的延迟任务(例如setTimeout
)将被放到下一轮宏任务中来执行。
const promise1 = new Promise((resolve, reject) => {
console.log('promise1')
})
console.log('1', promise1);
过程分析:
new Promise
,执行该构造函数中的代码promise1
1
,此时promise1
没有被resolve
或者reject
,因此状态还是pending
结果:
'promise1'
'1' Promise{<pending>}
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve('success')
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
过程分析:
new Promise
,执行其中的同步代码1
resolve('success')
, 将promise
的状态改为了resolved
并且将值保存下来2
promise
,往下执行,碰到promise.then
这个微任务,将其加入微任务队列4
promise.then
这个微任务且状态为resolved
,执行它。结果:
1 2 4 3
const promise = new Promise((resolve, reject) => {
console.log(1);
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
过程分析
promise
中并没有resolve
或者reject
promise.then
并不会执行,它只有在被改变了状态之后才会执行。结果:
1 2 4
const promise1 = new Promise((resolve, reject) => {
console.log('promise1')
resolve('resolve1')
})
const promise2 = promise1.then(res => {
console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);
过程分析:
new Promise
,执行该构造函数中的代码promise1
resolve
函数, 将promise1
的状态改变为resolved
, 并将结果保存下来promise1.then
这个微任务,将它放入微任务队列promise2
是一个新的状态为pending
的Promise
1
, 同时打印出promise1
的状态是resolved
2
,同时打印出promise2
的状态是pending
promise1.then
这个微任务且状态为resolved
,执行它。结果:
'promise1'
'1' Promise{<resolved>: 'resolve1'}
'2' Promise{<pending>}
'resolve1'
const fn = () => (new Promise((resolve, reject) => {
console.log(1);
resolve('success')
}))
fn().then(res => {
console.log(res)
})
console.log('start')
fn
函数它是直接返回了一个new Promise
的,而且fn
函数的调用是在start
之前,所以它里面的内容应该会先执行。
结果:
1
'start'
'success'
如果把fn
的调用放到start
之后呢?
const fn = () =>
new Promise((resolve, reject) => {
console.log(1);
resolve("success");
});
console.log("start");
fn().then(res => {
console.log(res);
});
是的,现在start
就在1
之前打印出来了,因为fn
函数是之后执行的。
答案:
"start"
1
"success"
console.log('start')
setTimeout(() => {
console.log('time')
})
Promise.resolve().then(() => {
console.log('resolve')
})
console.log('end')
过程分析:
start
和end
。setTimout
作为一个宏任务被放入宏任务队列(下一个)Promise.then
作为一个微任务被放入微任务队列Promise.then
,执行它setTimeout
,执行。结果:
'start'
'end'
'resolve'
'time'
const promise = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
console.log("timerStart");
resolve("success");
console.log("timerEnd");
}, 0);
console.log(2);
});
promise.then((res) => {
console.log(res);
});
console.log(4);
过程分析:
和题目1.2
很像,不过在resolve
的外层加了一层setTimeout
定时器。
new Promise
,执行该构造函数中的代码1
2
promise
函数,遇到promise.then
,但其状态还是为pending
,这里理解为先不执行4
setTimeout
定时器,执行它timerStart
,然后遇到了resolve
,将promise
的状态改为resolved
且保存结果并将之前的promise.then
推入微任务队列timerEnd
promise.then
这个微任务,执行它。因此执行结果为:
1
2
4
"timerStart"
"timerEnd"
"success"
题目三分了两个题目:
(1):
setTimeout(() => {
console.log('timer1');
setTimeout(() => {
console.log('timer3')
}, 0)
}, 0)
setTimeout(() => {
console.log('timer2')
}, 0)
console.log('start')
(2):
setTimeout(() => {
console.log('timer1');
Promise.resolve().then(() => {
console.log('promise')
})
}, 0)
setTimeout(() => {
console.log('timer2')
}, 0)
console.log('start')
执行结果:
'start'
'timer1'
'timer2'
'timer3'
'start'
'timer1'
'promise'
'timer2'
这两个例子,看着好像只是把第一个定时器中的内容换了一下而已。
一个是为定时器timer3
,一个是为Promise.then
但是如果是定时器timer3
的话,它会在timer2
后执行,而Promise.then
却是在timer2
之前执行。
你可以这样理解,Promise.then
是微任务,它会被加入到本轮中的微任务列表,而定时器timer3
是宏任务,它会被加入到下一轮的宏任务中。
Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise2')
})
}, 0)
console.log('start');
这道题稍微的难一些,在promise
中执行定时器,又在定时器中执行promise
;
并且要注意的是,这里的Promise
是直接resolve
的,而之前的new Promise
不一样。
因此过程分析为:
Promise.resolve().then
这个微任务,将then
中的内容加入第一次的微任务队列标记为微1timer1
,将它加入下一次宏任务的延迟列表,标记为宏2,等待执行(先不管里面是什么内容)start
promise.then
这个微任务需要执行promise1
,然后发现定时器timer2
,将它加入宏2的后面,标记为宏3timer1
promise2
这个微任务,将它加入此次循环的微任务队列,标记为微2promise2
,执行它timer2
所以结果为:
'start'
'promise1'
'timer1'
'promise2'
'timer2'
如果感觉有点绕的话,可以看下面这张图,就一目了然了。
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
const promise2 = promise1.then(() => {
throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)
过程分析:
new Promise
中的函数,碰到setTimeout
将它加入下一个宏任务列表new Promise
,碰到promise1.then
这个微任务,但其状态还是为pending
,这里理解为先不执行promise2
是一个新的状态为pending
的Promise
console.log('promise1')
,且打印出的promise1
的状态为pending
console.log('promise2')
,且打印出的promise2
的状态为pending
promise1
的状态改为resolved
且保存结果并将之前的promise1.then
推入微任务队列promise1.then
,它抛出了一个错误,且将promise2
的状态设置为了rejected
'promise1'
,且此时promise1
的状态为resolved
'promise2'
,且此时promise2
的状态为rejected
完整的结果为:
'promise1' Promise{<pending>}
'promise2' Promise{<pending>}
test5.html:102 Uncaught (in promise) Error: error!!! at test.html:102
'promise1' Promise{<resolved>: "success"}
'promise2' Promise{<rejected>: Error: error!!!}
如果你上面这道题搞懂了之后,我们就可以来做做这道了,你应该能很快就给出答案:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success");
console.log("timer1");
}, 1000);
console.log("promise1里的内容");
});
const promise2 = promise1.then(() => {
throw new Error("error!!!");
});
console.log("promise1", promise1);
console.log("promise2", promise2);
setTimeout(() => {
console.log("timer2");
console.log("promise1", promise1);
console.log("promise2", promise2);
}, 2000);
结果:
'promise1里的内容'
'promise1' Promise{<pending>}
'promise2' Promise{<pending>}
'timer1'
test5.html:102 Uncaught (in promise) Error: error!!! at test.html:102
'timer2'
'promise1' Promise{<resolved>: "success"}
'promise2' Promise{<rejected>: Error: error!!!}
总结:
Promise
的状态一经改变就不能再改变。(见3.1).then
和.catch
都会返回一个新的Promise
。(上面的Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。