padding(初始狀態)
、fulfilled(異步成功以後的狀態)
、rejected(異步失敗的狀態)
,改變狀態的方式只有一種
即異步的結果:若是成功狀態由padding——>fulfilled;不然狀態由padding——>rejected。沒法提供其餘方式改變狀態。new Promise((resolve, reject) => { if (異步成功後) { resolve(value)//將Promise的狀態由padding改成fulfilled } else { reject(error)//將Promise的狀態由padding改成rejected } }).then(value => { // resolve回調 }, error => { // reject回調 })
上面的代碼表示若是異步成功後就會調用.then()
裏面的第一個參數方法,不然就會調用.then()
裏面的第二個參數方法。若是調用resolve
和reject
有參數則會將參數分別傳遞給回調函數(.then裏面的第一個和第二個參數方法)。javascript
resolve
的參數除了正常值外還能夠是一個Promise
實例。如:java
let p1 = new Promise((resolve, reject) => { // ... }) let p2 = new Promise((resolve, reject) => { // ... resolve(p1) })
上面的代碼中p1
、p2
爲Promise實例。p2
的resolve
將p1
做爲參數。即:一個異步操做的結果是返回另外一個異步操做。
注意:
這時p1
的狀態決定了p2
的狀態。若是p1
的狀態爲padding
那麼p2
的回調會等p1
的狀態改變後執行(即p1
成功或失敗);若是p1
的狀態爲resolved
或rejected
那麼p2
的回調會當即執行。
示例:web
let p1 = new Promise((resolve, reject) => { setTimeout(()=>{ reject(new Error('發生錯誤嘹')) },3000) }) let p2 = new Promise((resolve, reject) => { setTimeout(()=>{ resolve(p1) },1000) }).then(value => { console.log(value) }).catch(error=>{ console.log(error) })
正由於如此上面代碼p2
最終執行的是catch()
方法,並不會走then()
方法。ajax
調用resolve
或reject
並不會終結 Promise 的參數函數的執行。
代碼示意:編程
new Promise((resolve, reject) => { setTimeout(()=>{ resolve('then') console.log('promise') },2000) }).then(value => { console.log(value) }) //執行結果 //promise //then
通常來講上面的console.log('promise')
若是要執行放到回調函數更加規範json
.then()的做用是爲 Promise 實例添加狀態改變時的回調函數
。
.then()方法的第一個參數是resolved
狀態的回調函數,第二個參數(可選)是rejected
狀態的回調函數。它的返回的是一個新的
Promise實例。所以能夠採用鏈式寫法。數組
getJSON("/post/1.json").then( post => getJSON(post.commentURL) ).then( comments => console.log("resolved: ", comments), err => console.log("rejected: ", err) )
上面代碼中,第一個then
方法指定的回調函數,返回的是另外一個Promise
對象。這時,第二個then
方法指定的回調函數,就會等待這個新的Promise
對象狀態發生變化。若是變爲resolved
,就調用funcA
,若是狀態變爲rejected
,就調用funcB
。promise
用於指定發生錯誤時的回調函數,最好是在.then()的鏈式調用最後調用一下此方法來捕獲異常。它的返回值仍然是個Promise對象異步
new Promise((resolve, reject) => { throw new Error('出現錯誤了') }).then(value => { }).catch(error=>{ console.log(error) })
上面代碼中若是Promise對象狀態變爲resolved
,則會調用then
方法指定的回調函數;若是異步操做拋出錯誤,狀態就會變爲rejected
,就會調用catch
方法指定的回調函數,處理這個錯誤。另外,then
方法指定的回調函數,若是運行中拋出錯誤,也會被catch
方法捕獲。svg
若是 Promise 狀態已經變成resolved
,再拋出錯誤是無效的。
new Promise((resolve, reject) => { resolve('data') throw new Error('出現錯誤了') }).then(value => { console.log(value) }).catch(error=>{ console.log(error) })
這時不會運行catch()裏面的方法
通常來講,不要在then方法裏面定義 Reject 狀態的回調函數(即then的第二個參數),老是使用catch方法。
若是沒有使用catch方法指定錯誤處理的回調函數,Promise 對象即使拋出錯誤也不會影響到其它代碼
finally
方法用於指定無論 Promise 對象最後狀態如何,都會執行的操做。該方法是 ES2018
引入標準的。
finally
方法的回調函數不接受任何參數,這意味着沒有辦法知道,前面的 Promise 狀態究竟是fulfilled
仍是rejected
。這代表,finally
方法裏面的操做,應該是與狀態無關的,不依賴於 Promise 的執行結果。
finally本質上是then方法的特例。以下代碼是等效的:
promise .finally(() => { // 語句 }); // 等同於 promise .then( result => { // 語句 return result; }, error => { // 語句 throw error; } );
Promise.all方法用於將多個 Promise 實例,包裝成一個新的 Promise 實例
const p = Promise.all([p1, p2, p3])
p1
、p2
、p3
都爲Promise實例,若是不是調用Promise.resolve
將它們轉成Promise實例。p
的狀態由p1
,p2
,p3
共同決定若是它們的狀態全都
爲fulfilled
則p
的狀態變成fulfilled
,此時p1
,p2
,p3
的返回值組成一個數組傳遞給p
的回調p1
,p2
,p3
中只要有一個爲rejected
,則p
的狀態變成rejected
,此時第一個被reject
的實例的返回值,會傳遞給p
的回調函數。p1
,p2
,p3
本身定義了catch方法,那麼它一旦被rejected,並不會觸發Promise.all()的catch方法const p1 = new Promise((resolve, reject) => { resolve('hello'); }) .then(result => result) .catch(e => e); const p2 = new Promise((resolve, reject) => { throw new Error('報錯了'); }) .then(result => result) .catch(e => e); Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e)); // ["hello", Error: 報錯了]
上面代碼中,p1
會resolved
,p2
首先會rejected
,可是p2
有本身的catch
方法,該方法返回的是一個新的 Promise 實例,p2
指向的其實是這個實例。該實例執行完catch
方法後,也會變成resolved
,致使Promise.all()
方法參數裏面的兩個實例都會resolved
,所以會調用then
方法指定的回調函數,而不會調用catch
方法指定的回調函數。若是p2
沒有本身的catch
方法,就會調用Promise.all()
的catch
方法。
此方法和Promise.all()同樣接收多個Promise實例,返回一個新的Promise實例。
const p = Promise.race([p1, p2, p3]);
和Promise.all()的不一樣之處
是隻要p一、p二、p3中有一個實例率先改變狀態,p的狀態就跟着改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數
Promise.resolve()的做用是將現有對象轉換成Promise對象。
如下的寫法是等效的
Promise.resolve('foo') // 等價於 new Promise(resolve => resolve('foo'))
參數是一個 Promise 實例,這種狀況Promise.resolve()什麼都不作
參數是具備then
方法的對象(thenable對象)
,Promise.resolve
方法會將這個對象轉爲Promise
對象,而後就當即執行thenable
對象的then
方法。例如:
let thenable = { then: function(resolve, reject) { resolve(42); } }; let p1 = Promise.resolve(thenable); p1.then(function(value) { console.log(value); // 42 });
上面代碼中,thenable
對象的then
方法執行後,對象p1
的狀態就變爲resolved
,從而當即執行最後那個then
方法指定的回調函數,輸出 42
參數不是具備then方法的對象,或根本就不是對象,Promise.resolve返回一個狀態爲resolved
的對象
const p = Promise.resolve('Hello'); // 由於p的狀態爲resolved因此.then()會當即執行 p.then(function (s){ console.log(s) }); // Hello
這種狀況直接返回狀態爲resolved的Promise對象。若是但願獲得一個 Promise 對象,比較方便的方法就是直接調用。
當即resolve
的 Promise 對象,是在本輪「事件循環」(event loop)的結束時,而不是在下一輪「事件循環」的開始時。示例:
setTimeout(function () { console.log('three'); }, 0); Promise.resolve().then(function () { console.log('two'); }); console.log('one'); // one // two // three
上面代碼中,setTimeout(fn, 0)
在下一輪「事件循環」
開始時執行,Promise.resolve()在本輪「事件循環」
結束時執行,console.log(‘one’)則是當即執行,所以最早輸出。
返回狀態爲rejected的Promise對象
如下兩種寫法等效
const p = Promise.reject('出錯了'); // 等同於 const p = new Promise((resolve, reject) => { reject('出錯了') }) p.catch(error=>{ console.log(error) }) // 出錯了