天天看點

ES6入門 :Promise 對象

ES6 規定,

Promise

對象是一個構造函數,用來生成

Promise

執行個體。

下面代碼創造了一個

Promise

執行個體。

const promise=new Promise(function(resolve,reject){
    if (/* 異步操作成功 */){
        resolve(value);
    } else {
        reject(error);
    }
})
           

Promise

構造函數接受一個函數作為參數,該函數的兩個參數分别是

resolve

reject

。它們是兩個函數,由 JavaScript 引擎提供,不用自己部署。

resolve

函數的作用是,将

Promise

對象的狀态從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并将異步操作的結果,作為參數傳遞出去;

reject

函數的作用是,将

Promise

對象的狀态從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并将異步操作報出的錯誤,作為參數傳遞出去。

Promise.prototype.then()

Promise 執行個體具有

then

方法,也就是說,

then

方法是定義在原型對象

Promise.prototype

上的。

作用是為 Promise 執行個體 添加 狀态改變時的回調函數。

第一個參數是

resolved

狀态的回調函數,第二個參數(可選)是

rejected

狀态的回調函數。

then

方法傳回的是一個新的

Promise

執行個體(注意,不是原來那個

Promise

執行個體)。是以可以采用鍊式寫法,即

then

方法後面再調用另一個

then

方法。

//Pending(等待、進行中) ---> Resolve(完成,fullFilled)   ---> Reject(拒絕,失敗)
var p1 = new Promise(function(resolve,reject){
    resolve(1); // 成功了
    // reject(2); // 失敗了
});

// 接收成功和失敗的資料,通過then來傳遞
// then也是傳回一個promise對象,會繼續往下傳遞資料,傳遞給下一個then
p1.then(function(value){
    // resolve
    console.log(value);
    return value + 1; // 1
    alert(`成功了:${value}`);
},function(value){
    // reject
    alert(`失敗了:${value}`);
}).then(function(value){
    console.log(value); // 2
});
           

Promise.prototype.catch()

用于指定發生錯誤時的回調函數。

var p1 = new Promise(function(resolve,reject){
    //resolve(1); // 成功了
     reject(2); // 失敗了
});
p1.then(function(value){
    // resolve
    console.log(value);
    return value + 1; 
}).catch(function(value){
    console.log(value); //2
    return value + 1;
}).then(function(value){
    console.log(value); // 3
});
           

then

方法指定的回調函數,如果運作中抛出錯誤,也會被

catch

方法捕獲。

//catch捕獲異常錯誤
var p1 = new Promise(function(resolve,reject){
    resolve('成功了');
});
p1.then(function(value){
    console.log(value);  // 成功了
    // throw是用來抛錯誤的
    throw '發生了點小意外';
}).catch(function(e){
    // catch用來捕獲這個錯誤的 ---> 追蹤
    console.log(e);  // 發生了點小意外
});
           

如果 Promise 狀态已經變成resolved,再抛出錯誤是無效的。

const promise = new Promise(function(resolve, reject) {
  resolve('ok');
  throw new Error('test');
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
// ok
           

 一般來說,不要在

then

方法裡面定義 Reject 狀态的回調函數(即

then

的第二個參數),總是使用

catch

方法。

Promise.all()

Promise.all

方法用于将多個 Promise 執行個體,包裝成一個新的 Promise 執行個體。

var p=Promise.all([p1,p2,p3])
           
//Promise.all([p1,p2,p3,...]); 所有的promise對象,都正确,才走成功
//否則,隻要有一個錯誤,就走失敗
var p1 = Promise.resolve(1);
var p2 = Promise.reject(0);
Promise.all([true,p1,p2]).then(function(obj){
    console.log(`成功了:${obj}`);
},function(obj){
    console.log(`失敗了:${obj}`);
});
           

Promise.race() 

var p=Promise.race([p1,p2,p3])
           
// race ---> 傳回的也是一個promise對象
//最先執行的的promise結果,哪個最快我用哪個
var p1 = new Promise(function(resolve,reject){
    setTimeout(resolve,50,'one');
});
var p2 = new Promise(function(resolve,reject){
    setTimeout(resolve,100,'two');
});
Promise.race([p1,p2]).then(function(val){
    console.log(val);
});
           

Promise.resolve() 

有時需要将現有對象轉為 Promise 對象,

Promise.resolve

方法就起到這個作用。

Promise.resolve

等價于下面的寫法。

Promise.resolve('foo')
// 等價于
new Promise(resolve => resolve('foo'))
           

應用

加載圖檔

将圖檔的加載寫成一個

Promise

,一旦加載完成,

Promise

的狀态就發生變化。

const preloadImage = function (path) {
  return new Promise(function (resolve, reject) {
    const image = new Image();
    image.onload  = resolve;
    image.onerror = reject;
    image.src = path;
  });
};
           

//Generator 函數 與 Promise結合