真的掌握了Promise的用法嗎?回顧一下Promise的特色,而後練習檢測一下吧。promise
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()中的回調函數oop
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()spa
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捕獲不到code
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捕獲cdn
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的任務分爲如下幾類:
當任務進入執行棧時,首先會判斷任務是同步的仍是異步的,同步的任務會被加入到主線程,異步的任務會被加入到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') }) })
1 7 6 8 2 4 9 11 3 10 5 12
作對了嗎?
注意:
Node中的process.nextTick獨立於事件循環以外, 優先級高於其餘微任務如: then()。