本文從js的異步處理出發,引入Promise的概念,而且介紹Promise對象以及其API方法。segmentfault
能夠參考這篇文章
js是單線程的,
在js裏,異步處理總共有四種方法,其中最多見的一種方法是採用回調函數的方式數組
function f1(callback){ setTimeout(function(){ callback(); },1000) } f1(f2);
另外除了回調函數,事件監聽的機制也會進行異步處理。任務的執行不取決於代碼的順序,而是取決於事件是否會發生。promise
若是是業務邏輯不復雜還好說,但是若是業務邏輯很複雜的話,回調嵌套的不少,代碼書寫起來會變得很複雜很難看懂。
還有一個問題是,若是有多個異步操做,那麼就存在一個處理順序的問題,代碼如何按照但願的順序執行。異步
Promise是抽象異步處理對象以及對其進行各類操做的組件。Promise並非從js裏出現的概念。
Promise則是把相似的異步處理對象和處理規則進行規範化, 並按照採用統一的接口來編寫,而採起規定方法以外的寫法都會出錯。函數
首先說,Promise是一個對象,因此說這個對象與js裏的其餘對象沒什麼不同的。要說不同凡響的地方時,Promise對象充當代理的做用,充當異步操做和回調函數之間的中介學習
Promise的思想是:每次執行一個異步操做之後,馬上返回一個Promise對象,由於是馬上操做,因此咱們能夠進行同步操做流程。這個Promise對象有一個then方法,指定回調函數,用於在異步操做執行完後執行回調函數處理。線程
//換成Promise的寫法 new Promise(f5).then(f4).then(f3).then(f2).then(f1)
使用Promise,用同步的寫法處理異步操做的代碼,使得代碼清晰易懂,等一個異步函數處理完成以後,纔會執行下一個then裏邊的函數。這樣就避免了前邊的多個回調可能引起的順序問題。代理
前邊說過,Promise接口的做用是,返回一個Promise對象。
一個Promise對象有三種狀態code
pending 異步操做未完成對象
resolve 異步操做已成功完成
reject 異步操做失敗
至於這三種關係的途徑能夠描述爲兩種
pending ---> resolve
pending ---> reject
這種變化只會出現一次。因此,意思是,一個異步操做結束以後只會有兩種狀態,成功or失敗。異步操做成功時,Promise對象返回一個值,對象狀態變爲resolve,異步操做失敗時,對象狀態變爲reject。
Promise對象用then方法添加回調函數,then方法支持鏈式調用。
promise.then(onFulfilled, onRejected)
then方法接受兩個參數,看名字就知道第一個參數是Promise對象狀態時resolve的時候調用,而第二個參數能夠省略,表示Promise調用失敗狀態是reject的時候執行這個回調。
除了then方法,還有一個專門處理異常的方法.
.catch 也能夠理解爲 promise.then(undefined, onRejected) 。
promise.catch(onRejected)
then和catch兩個方法是寫到了Promise對象的原型上的,每一個Promise對象均可以調用。
ES6提供了原生的Promise對象構造函數,用於生成Promise對象,
var promise = new Promise(function(resolve, reject){ // 異步操做的代碼 if (/* 異步操做成功 */){ resolve(value); } else { reject(error); } });
Promise對象接收一個函數做爲構造函數的參數,這個函數一樣有兩個參數,這兩個參數是由js引擎提供的函數,不用本身來部署。
resolve函數的做用是把Promise對象的狀態從pending變爲resolve,在異步操做成功的時候調用,而且將異步操做的結果做爲參數傳過去。一樣的,reject函數的做用是把對象狀態從pending變成reject,在失敗的時候調用,而且傳遞結果參數。
接下來,當Promise對象建立成功以後就能夠用then方法鏈式調用了。
通常狀況下,咱們會用構造函數的方法建立Promise對象。可是,除此以外咱們也會有其餘方法建立。
靜態方法Promise.resolve(value)被認爲是new Promise方式建立Promise對象的快捷方式。
Promise.resolve(42).then(function(value){ console.log(value); })
resolve()會讓對象狀態當即變成resolved,而且將形參馬上傳給下一個回調。
這個方法相似上一個方法,也是建立Promise對象的快捷方式,可是隻會把Promise對象從pending變爲rejected。參數是一個異常對象,傳遞給下一個catch方法或者then方法。
Promise.reject(new Error("BOOM!")).catch(function(error){ console.error(error); });
到目前爲止,已經學習了建立Promise對象和用then,catch方法來註冊回調函數。若是隻有一個Promise對象的話很好說,可是若是有多個Promise對象的時候要如何處理呢。
Promise.all 接收一個 promise對象的數組做爲參數,當這個數組裏的全部promise對象所有變爲resolve或reject狀態的時候,它纔會去調用 .then 方法。
Promise.race 只要有一個promise對象進入 FulFilled 或者 Rejected 狀態的話,就會繼續進行後面的處理。
function f1(v){ console.log(v); return 2; } function f2(v){ console.log(v) } Promise.resolve(1).then(f1).then(f2);