promise是一個很好的解決異步調用的方法,其鏈式調用也是一個很好的方式,這裏探究一下其調用過程
主要問題
Promise.resolve()
.then(res => {
return new Promise()
})
Promise.resolve()
.then(res => {
new Promise()
})
// 上下兩種Promise的方式中, 是否會進行下去,以及新產生的promise是否會被傳遞下去,或者說有什麼區別
測試代碼
每一句打印後面都輸出了時間戳,是爲了更好描述運行順序
測試代碼直接貼在下方,可以拿到瀏覽器中進行測試查看
;(function () {
// fn1()
// fn1_1()
// fn2()
// fn3()
// fn4()
// fn5()
// fn6()
// fn7()
// fn8()
// fn9()
})()
function fn1 () {
console.log('start', new Date().getTime())
new Promise(resolve => {
console.log('11111', new Date().getTime())
}).then(res => {
console.log('22222', new Date().getTime())
}).then(res => {
console.log('33333', new Date().getTime())
})
console.log('end', new Date().getTime())
/*
start 1560165694777
11111 1560165694787
end 1560165694790
*/
}
function fn1_1 () {
console.log('start', new Date().getTime())
new Promise(resolve => {
console.log('11111', new Date().getTime())
resolve()
console.log('11111-1111', new Date().getTime())
}).then(res => {
console.log('22222', new Date().getTime())
}).then(res => {
console.log('33333', new Date().getTime())
})
console.log('end', new Date().getTime())
/*
start 1560166834093
11111 1560166834106
11111-1111 1560166834108
end 1560166834110
22222 1560166834115
33333 1560166834119
*/
}
/*
通過前 fn1, fn1_1 兩個小例子可知,最開始的new Promise可能對我們進行干擾,
出現這種狀況的原因是,申明 new Promise的時候此時異步還未開始,所以我們
直接按照接下來的方式進行測試
*/
function fn2 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
})
.then(res => {
console.log('22222', new Date().getTime())
}).then(res => {
console.log('33333', new Date().getTime())
})
console.log('end', new Date().getTime())
/*
start 1560166657107
end 1560166657117
11111 1560166657120
22222 1560166657122
33333 1560166657130
*/
}
function fn3 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
}).then(res => {
console.log('22222', new Date().getTime())
return Promise.reject('2222error')
}).then(res => {
console.log('33333', new Date().getTime())
}).catch(err => {
console.log(err, new Date().getTime())
})
console.log('end', new Date().getTime())
/*
start 1560166779524
end 1560166779533
11111 1560166779537
22222 1560166779539
2222error 1560166779543
*/
}
/*
通過 fn3 這個例子知道了,只要在調用過程中,返回了一個Promise的reject狀態就會結束下去
*/
function fn4 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
return new Promise((resolve, reject) => { console.log('inner Promise', new Date().getTime())})
})
.then(res => {
console.log('22222', new Date().getTime())
}).then(res => {
console.log('33333', new Date().getTime())
}).catch(err => {
console.log(err, new Date().getTime())
})
console.log('end', new Date().getTime())
/*
start 1560167538395
end 1560167538407
11111 1560167538409
inner Promise 1560167538414
*/
}
/*
通過 fn4 這個例子,如果調用鏈中返回一個pending,
他也會等待(Promise創建出來就是pending狀態),
他既沒有reject,也沒有resovle。
到目前,一共有兩種方式會阻止鏈式,
① 返回了一個reject的Promise
② 返回pendding狀態的Promsie
其餘的情況都會暢通無阻的運行下去(前提直接就在調用鏈中了)
*/
function fn5 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
}).then(res => {
console.log('22222', new Date().getTime())
Promise.reject('2222error')
}).then(res => {
console.log('33333', new Date().getTime())
}).catch(err => {
console.log(err, new Date().getTime())
})
console.log('end', new Date().getTime())
/*
start 1560166933856
end 1560166933865
11111 1560166933869
22222 1560166933873
33333 1560166933874
(node:8196) UnhandledPromiseRejectionWarning: 2222error
*/
}
/*
通過 fn5 這個例子,其實那個新創建的Promise,並不屬於這個調用鏈,我們接着向下驗證
*/
function fn6 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
}).then(res => {
console.log('22222', new Date().getTime())
Promise.reject('2222error').then().catch(err => console.log('inner' + err, new Date().getTime()))
}).then(res => {
console.log('33333', new Date().getTime())
}).catch(err => {
console.log(err, new Date().getTime())
})
console.log('end', new Date().getTime())
/*
start 1560167831274
end 1560167831292
11111 1560167831296
22222 1560167831301
33333 1560167831307
inner2222error 1560167831316
*/
}
/*
通過 fn6 我們已經知道了在調用鏈中,如果return 出一個Promise,那麼
它將屬於此調用鏈,否則就會有他自己的一個調用鏈
*/
function timeout(ms) { // 這裏模擬一個異步操作
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
function fn7 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
return timeout(500)
}).then(res => {
console.log('22222', new Date().getTime())
return timeout(500)
}).then(res => {
console.log('33333', new Date().getTime())
return timeout(500)
}).catch(err => {
console.log(err, new Date().getTime())
return timeout(500)
})
console.log('end', new Date().getTime())
/*
start 1560167223744
end 1560167223759
11111 1560167223764
22222 1560167224274
33333 1560167224779
*/
}
function fn8 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
timeout(500)
}).then(res => {
console.log('22222', new Date().getTime())
timeout(500)
}).then(res => {
console.log('33333', new Date().getTime())
timeout(500)
}).catch(err => {
console.log(err, new Date().getTime())
timeout(500)
})
console.log('end', new Date().getTime())
/*
start 1560168006937
end 1560168006951
11111 1560168006954
22222 1560168006961
33333 1560168006966
*/
}
function fn9 () {
console.log('start', new Date().getTime())
Promise.resolve()
.then(res => {
console.log('11111', new Date().getTime())
timeout(500).then(res => { console.log('inner11111', new Date().getTime()) })
}).then(res => {
console.log('22222', new Date().getTime())
timeout(500).then(res => { console.log('inner22222', new Date().getTime()) })
}).then(res => {
console.log('33333', new Date().getTime())
timeout(500).then(res => { console.log('inner33333', new Date().getTime()) })
}).catch(err => {
console.log(err, new Date().getTime())
timeout(500).then(res => { console.log('inner44444', new Date().getTime()) })
})
console.log('end', new Date().getTime())
/*
start 1560168109766
end 1560168109775
11111 1560168109778
22222 1560168109781
33333 1560168109785
inner11111 1560168110281
inner22222 1560168110288
inner33333 1560168110291
*/
}
/*
最後通過 fn7, fn8, fn9 這三個例子中,以及傳入的時間,
確實印證了之前所說的,這裏用一副圖進行代替。
所以最爲關鍵的就是,在Promise的調用鏈中,關鍵要明白你新產生的這個 Promsie
是否添加到了這個調用鏈中
*/