20170702-異步編程之Promise

1.Promise的含義

  • Promise是異步編程的一種解決方案javascript

  • Promise實例表明一個異步操做,從它能夠獲取異步操做的消息html

  • Promise實例有三種狀態:java

    • Pending:進行中es6

    • Resolved:已完成編程

    • Rejected:已失敗json

  • Promise實例的狀態只能由 Pending->ResolvedPending->Rejected。一旦Promise實例的狀態發生改變,就不會再發生變化,任什麼時候候均可以獲得這個結果數組

  • 爲何要使用Promise:經過Promise,能夠將一步操做以同步操做的流程表達出來,能夠避免層層嵌套的回調函數(回調地域),而且Promise提供了統一的接口,使得控制異步操做更加容易promise

2.Promise構造函數

Promise是一個構造函數,用來生成Promise實例異步

var promise = new Promise(function(resolve, reject)){
    // ... do something
    if (/*異步操做成果*/) {
        resolve(value)
    } else { /*異步操做失敗*/
        reject(error)
    }
}
  • Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolvereject。它們是兩個函數,由 JavaScript 引擎提供,不用本身部署。異步編程

  • resolve函數的做用是,將Promise實例的狀態從「未完成」變爲「成功」(即從 Pending 變爲 Resolved),在異步操做成功時調用,並將異步操做的結果,做爲參數傳遞出去

  • reject函數的做用是,將Promise實例的狀態從「未完成」變爲「失敗」(即從 Pending 變爲 Rejected),在異步操做失敗時調用,並將異步操做報出的錯誤,做爲參數傳遞出去**

Promise.prototype.then()

Promise實例生成之後,能夠用then方法分別指定Resolved狀態和Reject狀態的回調函數。

var promise = new Promise(function(resolve, reject)){
    // ... do something
    if (/*異步操做成果*/) {
        resolve(value)
    } else { /*異步操做失敗*/
        reject(error)
    }
}
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
  • then方法能夠接受兩個回調函數做爲參數。第一個回調函數是Promise的狀態變爲Resolved時調用,第二個回調函數是Promise實例的狀態變爲Rejected時調用。其中,第二個函數是可選的,不必定要提供。

  • 這兩個函數都接受Promise實例傳出的值做爲參數。(簡單地說就是:上面的promise對象在處理異步操做的過程當中,若是調用了resolve方法,則會將resolve的參數傳遞給then方法的第一個函數,若是調用了reject方法,這會將reject的參數傳遞給then方法的第二個函數)

clipboard.png

then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例),所以能夠採用鏈式寫法,即then方法後面在調用另外一個then方法

clipboard.png

上面的代碼使用then方法,依次指定了兩個回調函數。第一個回調函數完成之後,會將返回結果做爲參數,傳入第二個回調函數。(其實是第一個then方法返回了一個Promise實例,在該實例中調用了resolve方法,而json.post則是做爲resolve的參數)


clipboard.png

上面代碼中,第一個then方法指定的回調函數,返回的是另外一個Promise實例,則第一個then方法會直接將該Promise實例返回

Promise.prototype.catch()

該方法是.then(undefined, onRejected)的別名,用於指定發生錯誤時的回調函數。

promise.then(function(data) {
    console.log('success');
}).catch(function(error) {
    console.log('error', error);
});

promise對象的錯誤,會一直向後傳遞,直到被捕獲。即錯誤總會被下一個catch所捕獲。then方法指定的回調函數,若拋出錯誤,也會被下一個catch捕獲。catch中也能拋錯,則須要後面的catch來捕獲。

sendRequest('test.html').then(function(data1) {
    //do something
}).then(function (data2) {
    //do something
}).catch(function (error) {
    //處理前面三個Promise產生的錯誤
});

Promise.all()

該方法用於將多個Promise實例,包裝成一個新的Promise實例

// p1,p2,p3都是promise實例
var p = Promise.all([p1, p2, p3]);

新的Promise實例的狀態由三個promise實例共同決定

  • 當三個promise實例的狀態都變爲fulfilled,p的狀態纔會變爲fulfilled,並將三個promise返回的結果,按照參數順序存入數組,傳給p的回調函數

  • 當p1, p2, p3其中之一狀態變爲rejected,p的狀態也會變爲rejected,並把第一個被reject的promise的返回值,傳給p的回調函數

Promise..race()

該方法用於將多個Promise實例,包裝成一個新的Promise實例

// p1,p2,p3都是promise實例
var p = Promise.race([p1, p2, p3]);

新的Promise實例的狀態由三個promise實例共同決定

  • 當p1, p2, p3其中之一狀態發生改變(變爲fulfilled或者rejected),p的狀態也會隨之改變,並把第一個改變狀態的promise的返回值,傳給p的回調函數

Promise.resolve()

Promise.resolve方法的參數分爲四種狀況

  • 參數是一個Promise實例

若是參數是Promise實例,那麼Promise.resolve將不作任何修改、原封不動地返回這個實例。

  • 參數是一個thenable對象

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});

Promise.resolve方法會將這個對象轉爲Promise對象,而後就當即執行thenable對象的then方法。

  • 參數不是具備then方法的對象,或根本就不是對象

若是參數是一個原始值,或者是一個不具備then方法的對象,則Promise.resolve方法返回一個新的Promise對象,狀態爲Resolved。

Promise.resolve('Success');

/*******等同於*******/
new Promise(function (resolve) {
    resolve('Success');
});
  • 不帶任何參數

直接返回一個Resolved狀態的Promise對象。

Promise.resolve('Success');

/*******等同於*******/
new Promise(function (resolve) {
    resolve();
});

Promise.reject()

Promise.reject(new Error('error'));

/*******等同於*******/
new Promise(function (resolve, reject) {
    reject(new Error('error'));
});

這段代碼會讓這個Promise對象當即進入rejected狀態,並將錯誤對象傳遞給then指定的onRejected回調函數。

參考資料

ECMAScript 6 入門

相關文章
相關標籤/搜索