使用Promise中,鏈式的調用對於控制異步執行很重要。css
在jQuery的使用中,咱們經常使用下面的代碼node
$('#app').show().css("color","red");
這是由於jQuery的對象在調用上述方法的時候,會return
此對象自己, 以方便後面能夠繼續調用此對象的方法。segmentfault
jQuery.fn.css = function(prop, value) { ...... return this; } jQuery.fn.show = function() { ...... return this; }
Promise是支持鏈式調用的,可是它是不一樣於上面jQuery的鏈式。jQeury是調用方法返回自身,可是Promise是調用方法後返回一個新的Promise。promise
const promise = new Promise((resolve, reject) => { resolve('ok'); }) const promise$1 = promise.then(() => {console.log()}); promise$1 === promise // false
能夠看到上面的promise$1是不等於promise的,若是能夠在node.js 或者在瀏覽器中進行斷點調試的話,還能看到promise$1的初始化狀態是pending的。
瀏覽器
當Promise的實例使用then, catch, finally添加完回調方法
之後,會返回一個初始化狀態爲pending
的Promise的實例對象。此對象的狀態咱們在外部的程序是沒法進行改變的,它的狀態取決於前面所註冊的回調方法
的執行狀況。 當回調方法
運行正常,沒有產生錯誤或者異常,返回的值除Promise實例與自己(返回自己將會報錯),返回的Promise的實例對象狀態會變成resolved, 若是有錯誤或者異常,則會把狀態變爲rejected。固然了返回值是Promise的實例對象,那麼次Promise實例對象的狀態取決於返回的Promise實例對象的狀態。 app
下圖以then爲例展現promise鏈式調用運行的流程異步
const promise$0 = Promise.resolve('resolve_0'); const promise$1 = new Promise((resolve, reject) => {resolve('resolve_1')}) promise$0.then((val) => { console.log(val) }).then(() => { console.log('continue') }); promise$1.then((val) => { console.log(val) }); //輸出結果: resolve_0 resolve_1 continue
promise$0與promise$1在使用then添加回掉函數以前,狀態已經從pending變爲resolved,它們添加的回掉函數會被當即添加到Promise的運行隊列,promise$0.then((val) => { console.log(val) })
返回的Promise實例須要等待所註冊的回調函數成功執行完畢之後,此Promise的狀態才從pending變爲resolved。 Promise的運行機制請參考: Promise的運行機制函數
const promise = Promise.resolve('ok'); promise.then().then((val) => {console.log(val)}); // ok
因爲promise經過then沒有成功添加回調函數,發生了值穿透。this
const promise = Promise.resolve('complete'); promise.then((val) => { return new Promise ((resolve) => { resolve(val) console.log(val, 1); }) }) .then((val) => {console.log(val, 2)}) // complete 1 complete 2
咱們把Promise暫命名(Pa), 經過promise.then返回的Promise(暫命名Pb), Pb
狀態須要根據Pa
then所註冊回調方法的運行,其回調方法返回一個新的Promise(暫命名Pc),因爲返回的是Promise。Pb
的狀態變成取決於Pc
的狀態, 當Pc
的狀態變化爲resolved之後,Pb
的狀態也變化爲resolved。spa
var promise = Promise.resolve('ok'); promise.then(() => { throw new Error('error'); }).then(() => { console.log('continue'); }).then(() => { console.log('again'); }).catch(() => { }).then(() => { console.log('completed') }) // completed
在then所註冊的回調方法,發生異常之後,後續的Promise調用鏈的狀態都是rejected,致使後續的then(resolve)
不會被推入Promise的運行隊列,也就不會被運行,直到這個錯誤被then(,reject)
或者catch
捕獲。 而使用(then(,reject))
或者catch
註冊回調方法又會返回一個新的Promise,此Promise的狀態又只與它們所註冊的回調方法的執行相關。不會受到前面的影響。