仅记录个人不太理解promise的地方的解释
- 给new Promise()传递的执行器函数是同步执行的,即Promise新建后就会立即执行(reslove()之后的代码会执行)
- promise.then()是微任务,并且在promise状态改变后执行
- 每一个promise.then()或promise.catch()返回一个新的promise,如果promise.catch()正常执行完,返回的这个新的promise fulfilled
- Promise状态只能改变一次 如下,可以把不清楚的地方写出来跑一下,写出预期输出,对比实际输出,看自己理解的误差在哪
const promise = new Promise((resolve, reject) => {
console.log('宏任务1start')
resolve('promise状态改变')
})
setTimeout(() => {
console.log('宏任务2start')
}, 0)
promise.then(function fulfilled(value) {
console.log('宏任务1-微任务ful1', value)
throw new Error('报错吧!')
},function rejected(reason) {
console.log('宏任务1-微任务reject1', reason)
}).then((value) => {
console.log('宏任务1-微任务ful2', value)
}).catch((reason)=> {
console.log('宏任务1-微任务reject3', reason)
}).then((value) => {
console.log('宏任务1-微任务ful4', value)
}).catch((reason)=> {
console.log('宏任务1-微任务reject5', reason)
})
console.log('宏任务1end')
// 预期输出:宏1start 宏1end 宏1微ful1,状态改变 宏1微reject3,Error 宏1微ful4,undefined 宏2start
// 实际输出:
// 宏任务1start
// 宏任务1end
// 宏任务1-微任务ful1 promise状态改变
// 宏任务1-微任务reject3 Error: 报错吧!
// 宏任务2start
改变一下
const promise = new Promise((resolve, reject) => {
console.log('宏任务1start')
setTimeout(() => {
console.log('宏任务2start')
resolve('promise状态改变')
}, 0)
})
promise.then(function fulfilled(value) {
console.log('宏任务1-微任务ful1', value)
throw new Error('报错吧!')
},function rejected(reason) {
console.log('宏任务1-微任务reject1', reason)
}).then((value) => {
console.log('宏任务1-微任务ful2', value)
}).catch((reason)=> {
console.log('宏任务1-微任务reject3', reason)
}).then((value) => {
console.log('宏任务1-微任务ful4', value)
}).catch((reason)=> {
console.log('宏任务1-微任务reject5', reason)
})
console.log('宏任务1end')
// 预期输出:宏1start 宏1end 宏2start 宏1微ful1,状态改变 宏1微reject3,Error 宏1微ful4,undefined
// 实际输出:
// 宏任务1start
// 宏任务1end
// 宏任务2start
// 宏任务1-微任务ful1 promise状态改变
// 宏任务1-微任务reject3 Error: 报错吧!
// 宏任务1-微任务ful4 undefined
注意输出顺序的改变,由于resolve('promise状态改变')被放在setTimeout()中,所以后续的promise.then()会在setTimeout()执行完之后才被执行,对应第2点 再来一个
const promise = function() {
return new Promise((resolve, reject) => {
const p1 = new Promise((resolve, reject) =>{
setTimeout(() =>{
resolve(1) // 没用了!
}, 0)
resolve(2)
})
p1.then((res) => {
console.log(res)
})
console.log(3)
resolve(4)
})
}
promise().then((res) => {
console.log(res)
})
console.log('end')
// 预期输出 3 end 2 4
// 实际输出
// 3
// end
// 2
// 4
p1.then()入微任务队列,打印3,promise().then()入微任务队列,打印end
开始执行微任务队列,打印2,打印4
注意resolve(1)没有作用了,对应第4点
再来结合一下async await
async function async1() {
console.log('async1')
await async2() // 相当于new Promise((resolve)=>{}).then(()=>{})
console.log('asnyc1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
async1()
new Promise((resolve, reject) => {
console.log('promise')
resolve()
}).then(function fulfilled(){
console.log('promise2')
})
console.log('script end')
// 输出
// script start
// async1
// async2
// Promise
// script end
// async1 end
// promise2
await相当于把之后的代码放入new Promise().then()中,即
new Promise((resolve, reject)=>{
async2()
resolve()
}).then(function(){
console.log('async1 end')
})
这里再延伸一下,如果这么改写
new Promise((resolve, reject)=>{
async2()
resolve()
}).then(
console.log('async1 end') // 直接同步打印了,为什么???
)
这里为什么直接打印了?console.log()是作为参数传入.then()方法,也就是这里.then()接收到的参数都是console.log()的执行结果undefined。
async function async1() {
console.log('async1')
// await async2()
// console.log('asnyc1 end')
const result = new Promise((resolve, reject)=>{
async2()
resolve('async1 resolve')
}).then(
console.log('async1 1'),
console.log('async1 2'),
console.log('async1 3')
)
setTimeout(()=>{ // 这里打印一下结果
console.log(result)
}, 0)
}
async function async2() {
console.log('async2')
}
console.log('script start')
async1()
new Promise((resolve, reject) => {
console.log('promise')
resolve()
}).then(function fulfilled(){
console.log('promise2')
})
console.log('script end')
// 输出
// script start
// async1
// async2
// async1 1
// async1 2
// async1 3
// promise
// script end
// promise2
// Promise { 'async1 resolve' }
可以看到.then()中的console.log()都执行了,而最终打印的result的value为new Promise()的resolve()的value,这是为什么呢?不是说.then()返回一个新的Promise吗?根据Promise A+规范,onFulfilled如果不是函数,应该被忽略,这里的忽略是指原样返回value,onRejected同理。这里没有取到一个是函数的onFulfilled。 这样写可以看到新增为任务了,value修改了,console.log()也依然同步执行了。
async function async1() {
console.log('async1')
// await async2()
// console.log('asnyc1 end')
const result = new Promise((resolve, reject)=>{
async2()
resolve('Promise resolve')
}).then(
function() {
console.log('async1 fulfilled')
return 'then resolve'
},
console.log('async1 1'),
console.log('async1 2'),
console.log('async1 3'),
)
setTimeout(()=>{
console.log(result)
}, 0)
}
async function async2() {
console.log('async2')
}
console.log('script start')
async1()
new Promise((resolve, reject) => {
console.log('promise')
resolve()
}).then(function fulfilled(){
console.log('promise2')
})
console.log('script end')
// 输出
// script start
// async1
// async2
// async1 1
// async1 2
// async1 3
// promise
// script end
// async1 fulfilled
// promise2
// Promise { 'then resolve' }
补充一点Node.js事件循环容易混淆的点 1.主程序中setImmediate()和setTimeout()的执行顺序不一定,但是在同一timers回调或同一I/O回调中,setImmediate()一定先于setTimeout() 2.同一轮微任务中,process.nextTick优先级高于promise.then()