前言
上一篇写了Promise的用法。
真的掌握了Promise的用法吗?回顾一下Promise的特点,然后练习检测一下吧。
Promise的特点
- Promise构造函数是同步的,promise.then()中的函数是异步的
- Promise只能从pending->resolve或pending->reject,状态一但改变就不能再变
- Promise.then、Promise.catch中不能return promise对象本身
- Promise.then中必须是函数
Practice 1:
const promise3 = new Promise((r, j) => {
r('success')
j('error')
r('success2')
})
promise3
.then(res => {
console.log('then:', res)
})
.catch(err => {
console.log('error:', err)
})
//success
状态一旦改变就不能再变
Practice 2:
Promise.resolve(1)
.then(res => {
console.log(res)
return 2
})
.catch(err => {
console.log(err)
return 3
})
.then(res => {
console.log(res)
})
// 1
// 2
链式调用,then()中return的结果正常情况下会传递给后面的then()中的回调函数
Promise.resolve(1)
.then(res => {
console.log(res)
return new Error('error')
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(('error', err))
return 3
})
return error对象时也不会被catch捕获,除非throw 一个error对象或者return Promise.reject()
new Promise((r, j) => {
j('failed')
})
.then(
function success(res) {
return res
},
function failed(err) {
console.log('failed:', err)
}
)
.then(res => {
console.log(res)
})
.catch(err => {
console.log('catch:', err)
return 3
})
//failed: failed
then(resolve, reject).catch()
catch是then的第二个参数的简写,reject捕获上一个函数的错误,这个时候catch捕获不到
new Promise((r, j) => {
r('success')
})
.then(
function success(res) {
throw new Error('error')
return res
},
function failed(err) {
console.log('failed:', err)
}
)
.then(res => {
console.log(res)
})
.catch(err => {
console.log('catch:', err)
return 3
})
//catch: Error: error
如果是then中的第一个回调函数抛出错误,会被catch捕获
Practice 3:
new Promise((r, j)=> {
console.log(1)
r()
console.log(2)
}).then(()=> {
console.log(3)
})
console.log(4)
//1 2 4 3
const promise1 = new Promise((r, s) => {
setTimeout(() => {
console.log('success')
r('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)
做对了吗?如果错了,回顾下Js的执行机制吧。
回顾下Js的事件循环
Js执行机制是事件循环,Js是单线程的语言,执行多个任务时需要按顺序执行。Js的任务分为以下几类:
- 广义上Js任务分为:同步任务和异步任务。
- 狭义上Js任务分为:宏任务(setTimeout、setInterval、script)和微任务(promise.then、promise.nextTick)(任务指的是这些方法里面的回调函数)。**
当任务进入执行栈时,首先会判断任务是同步的还是异步的,同步的任务会被加入到主线程,异步的任务会被加入到event table,注册函数;当异步任务完成返回结果时,event table会将函数移入到event queue(任务队列),这个任务队列中包含了2种任务:微任务和宏任务。
当Js执行任务时,首先将主线程的任务执行完,然后再将任务队列中的任务加入到主线程中执行;这个过程中首先会将任务队列中的微任务加入到主线程中执行,执行完然后再取任务队列中的宏任务到主线程执行,执行完再进入下一个循环,依此类推...
process.nextTick(() => {
console.log('nextTick')
})
new Promise((r, s) => {
console.log('promise')
r()
}).then(() => {
console.log('then')
})
setImmediate(() => {
console.log('immediate')
})
console.log('end')
promise
end
nextTick
then
immediate
最后检验自己是否掌握的一个例子:
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
在node中的结果:
1 7 6 8 2 4 9 11 3 10 5 12
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
在浏览器中的结果:
1 7 8 2 4 5 9 11 12
做对了吗?
注意:
- Node中的process.nextTick独立于事件循环之外, 优先级高于其他微任务如: then()。
- 浏览器和 Node 环境下,microtask 任务队列的执行时机不同
Node 端,microtask 在事件循环的各个阶段之间执行
浏览器端,microtask 在事件循环的 macrotask 执行完之后执行
可以参考:浏览器与Node的事件循环(Event Loop)有何区别
最近更新:2020-03-27
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。