Promise 是異步編程的一種解決方案,比傳統的解決方案--回調函數和事件更合理、更強大。
簡單來講就是一個容器,裏面保存着某個將來纔會結束的事件(也就是異步操做)的結果。從語法上來說,Promise是一個對象,從它能夠獲取異步操做的消息,它提供統一的API,各類異步操做均可以用一樣的方法進行處理。
1.1.一、對象的狀態不受外界影響。Promise對象表明一個異步操做,有三種狀態:pending(進行中)、fulfilled(已成功)和 rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態、任何其餘操做都沒法改版這個狀態。編程
1.1.二、一旦狀態改版,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只存在兩種可能:從 pending 變爲 fulfilled 和 從 pending 變爲 rejeced。只要這兩種狀況發生,狀態就終止,不會再變了並一直保持這個結果。這時就稱爲 resolved(已定型)。若是改版已經發生了,即便再對Promise對象添加回調函數,也會當即獲得這個結果。若是你錯過了再想去監聽,是得不到結果的。數組
1.1.三、有了Promise對象,就能夠將異步操做以同步操做的流程顯示出來,這樣就避免了層層嵌套的回調函數。Promise對象提供統一的接口,使得控制異步操做更加容易。promise
1.1.四、Promise也有一些缺點,就是沒法取消 Promise,一旦創建就會當即執行,沒法中途取消。若是不設置回調函數,Promise內部拋出的錯誤不會反應到外部。另外若是處於 pending 狀態時,是沒法知道如今到了哪個階段。異步
Promise對象是一個構造函數,用來生成Promise實例
const promise = new Promise((reolve, reject) => { if (// 異步操做成功) { resolve(val) }else{ reject(val) } })
Promise 構造函數接受一個函數做爲參數,該函數的兩個參數分別是 resolve 和 reject。異步編程
resolve:,將Promise對象的狀態從『未完成』變爲『成功』(pending => resolved),在異步操做成功時調用,並將異步操做的結果做爲參數傳遞出去。函數
reject:將Promise對象的狀態從『未完成』變爲『失敗』(pending => rejected),在異步操做失敗時調用,並將異步操做的結果做爲參數傳遞出去。spa
Promise 實例生成之後,能夠用 then 方法分別指定 resolved 狀態和 rejected 狀態的回調函數。prototype
promise.then((val) => { // success },(err) => { // failure })
then方法能夠接受兩個回調函數做爲參數。(第二個函數可選,這兩個函數都接受Promise對象傳出的值做爲參數)code
一、第一個回調函數在Promise對象的狀態變爲『resolved』時調用。對象
二、第二個回調函數在Promise對象的狀態變爲『rejected』時調用。
實例: function timeout(ms) { retrun new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done') }) } timeout(100) .then((v) => { console.log(v) })
上面代碼中,timeout方法返回一個Promise實例,表示一段時間之後纔會發生的結果,過了 ms時間後,Promise狀態變爲『resolved』而後就會觸發then方法綁定的回調函數。
Promise 創建後就會當即執行
let promise = new Promise((resolve, reject) => { console.log('Promise') resolve() }) promise .then(() => { console.log('resolved') }) console.log('hh') // Promise // hh // resolved
Promise創建後當即執行,首先輸出 「Promise」而後執行promise 的then函數,而後首先執行同步任務 輸出 hh 在執行 then方法的回調函數輸出resolved
若是調用 resolve 函數和 reject 函數時帶有參數,那麼它們的參數會被傳遞給回調函數。reject函數的參數一般是Error對象的實例,表示拋出的錯誤。resolve函數的參數除了正常的值之外,還有多是一個Promise實例。resolve實在成功的時候調用,reject是在失敗的時候調用。
const p1 = new Promise(function (resolve, reject) { // ... }); const p2 = new Promise(function (resolve, reject) { // ... resolve(p1); })
上述代碼中:p1 和 p2都是Promise的實例,可是p2的 resolve方法將 p1做爲參數,即一個異步操做的結果返回是另外一個異步操做。
注意:p1的狀態就會傳遞給p2,p1的狀態決定了p2的狀態。若是p1的狀態是pending,那麼p2的回調函數就會等待p1的狀態改變;若是p1的狀態已是 resolved 或者 rejected,那麼p2的回調函數會當即執行。
通常來講,調用resolve 或 reject之後,Promise的進程就就結束了,後續操做應該放到 then方法裏,而不是直接寫在 resolve 或 reject 的後面。另外最後在它們以前加上 return語句。
Promise實例具備 then 方法,then方法是定義在原型對象 Promise.prototype上的。它的做用是爲 Promise 實例添加狀態改變時的回調函數。then 的第一個參數是 resolved狀態的回調函數,第二個參數是 rejected狀態的回調函數。
then方法返回的是一個新的 Promise 實例,不是原來那個,所以可使用鏈式寫法。.then().then()
a().then((j) => { retrun j }).then((i) => { console.log(i) },(err)=>{ console.log(err) })
上面 第一個then方法指定的回調函數,返回的是另外一個 Promise 對象。這時,第二個 then 方法指定的回調函數,就會等這個新的 Promise對象狀態發生變化,若是變爲 resolved,就調用第一個回調函數,若是狀態變爲 rejected,就調用第二個回調函數。
Promise.prototype.catch 方法是 .then(null, rejecton) 或 .then(undefined, rejection)的別名,用於指定發生錯誤時的回調函數。
a().then((p) => { // success }).catch((err) => { console.log('err') })
若是對象的狀態變爲 resolved, 則會調用 then 方法指定的回調函數 success,若是異步操做拋出錯誤,狀態就會變爲 rejected,就會調用 catch 方法指定的回調函數處理這個錯誤。若是 then 方法指定的回調函數,在運行中拋出錯誤,也會被catch 方法捕獲。
另外reject方法的做用等同於拋出錯誤
若是 Promise狀態已經變成 resolved,再拋出錯誤是無效的。由於狀態一旦改版,就永遠保持,不會再變了。 並且Promise的錯誤有『冒泡』的性質,會一直向後傳遞,直到被捕獲位置,它的錯誤總會被下一個catch語句捕獲。
建議:Promise 對象後面要跟catch方法,這樣能夠處理 Promise 內部發生的錯誤。catch方法返回的仍是一個 Promise 對象,所以後面還能夠接着調用then方法。
注意: catch函數中的方法發生錯誤,若是後面沒有別的catch 方法,那麼錯誤將不會被捕獲,若是 catch 後面 還有catch ,第二個catch將會捕獲前一個catch方法拋出的錯誤。
finally 方法用於指定無論 Promise 對象最後狀態如何,都會執行的操做。
promise .then(result => {···}) .catch(error => {···}) .finally(() => {···});
以上,無論promise 最後的狀態,都會執行 finally 方法指定的函數。
finally 方法的回調函數不接受任何參數,因此就沒法知道以前Promise狀態究竟是 fulfilled 仍是 rejected。因此在finally方法裏面的操做,是與以前狀態無關的並且不依賴於Promise的執行結果。
Promise.all 方法用於將多個 Promise 實例,包裝成一個新的 Promise實例。
const p = Promise.all([p1, p2, p3])
Promise.all 方法接受一個數組做爲參數,p一、p二、p3都是Promise實例,若是不是,就會先調用Promise.resolve方法,將參數轉爲 Promise 實例再處理。(Promise.all 方法的參數能夠不是數組,但必須具備 Iterator 接口,且返回的每一個成員都是 Promise 實例。)
一、若是 p1 p2 p3的狀態都變成了 fulfilled,p的狀態纔是fulfilled,這時候返回一個 p1 p2 p3返回值組成的數組,傳遞給 p 的回調函數。
二、若是 p1 p2 p3中任一一個被rejected,p 的狀態就變成了 rejected,這時候返回的是第一個被 rejected 實例的返回值,傳遞給 p 的回調函數。
注意,若是做爲參數的 Promise 實例,本身定義了catch方法,那麼它一旦被rejected,並不會觸發Promise.all()的catch方法。而是觸發本身定義的catch方法。
Promise.race方法一樣是將多個 Promise 實例,包裝成一個新的 Promise實例。
const p = Promise.race([p1, p2, p3]);
與 Promise.all 的區別就是 p1 p2 p3 中一個實例改變狀態,那麼 p 的狀態就跟着改變了,返回值爲最早返回那個Promise實例的返回值。
將現有對象轉爲 Promise 對象。
那麼將不作任何修改。
將這個對象轉爲Promise對象,而後當即執行 thenable對象的then方法
返回一個新的Promise對象,狀態爲 resolved
直接返回一個 resolved 狀態的Promise對象
Promise.reject(reason)方法也會返回一個新的 Promise 實例,該實例的狀態爲rejected。回調函數當即執行。