Promise對象

Promise對象的特點:

1、對象的狀態不受外界影響。promise對象代表一個異步操作,有3種狀態:Pending(進行中)、Fulfilled(已成功)、Rejected(已失敗)。

2、一旦狀態改變就不會再變。因此它的狀態改變只有兩種可能:Pending到Fulfilled,Pending到Rejected。

基本用法

Promise構造函數接受一個函數作爲參數,該參數的兩個參數分別是resolve和reject,他們是兩個函數。

生成實例後,可以用then方法分別指定Resolved狀態和Rejected狀態的回調函數。then方法可以接收兩個參數,第一個是promise對象的狀態變爲Resolved時調用,第二個是狀態變爲Rejected狀態時調用,第二個參數可選,此時可以調用catch方法,catch除了狀態變爲Rejected時會調用以外,也會捕獲Promise對象中的錯誤。建議使用catch,而不是使用then的第二個參數。

var p = new Promise(resolve,reject){
    console.log('promise');
    if(/*異步操作成功*/){
        resolve(value);
    }else{
        reject(reason);
    }
}
p.then(function(value){
    //狀態變爲resolve時的回調
    console.log(value)
},function(error){
    //狀態變爲reject時的回調
    console.log(error)
});
//使用catch
p.then(function(value){
    console.log(value)
}).catch(function(error){
    console.log(error)
})

TIPS:promise裏的代碼是同步執行,then裏的回調是異步執行

Promise.prototype.then()、Promise.prototype.catch()

返回一個新的promise對象,可以繼續調用這個新對象的then或catch方法,其參數爲第一個then方法或catch方法的返回值。

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('resolve');
    }, ms);
  });
}
async function asyncPrint(value, ms) {
  timeout(ms)
    .then(res => {
      return res;
    })
    .then(res => {
      console.log(
        '第一個then方法返回promise對象,其return的值爲第二個then回調的參數::' +
          res
      );
    });
}
asyncPrint('hello world', 1000);

catch未返回Promise.reject時,此新promise對象會走到then回調裏:

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('reject');
    }, ms);
  });
}
async function asyncPrint(value, ms) {
  timeout(ms)
    .then(res => {
      return res;
    })
    .catch(error => error)
    .then(res => {
      console.log(
        'catch方法返回promise對象,其return的值爲第二個then回調的參數::' +
          res
      );
    });
}
asyncPrint('hello world', 1000);

catch返回Promise.reject時,此新promise對象會走到catch回調裏:

//catch返回了reject錯誤,因此需要後面調用catch方法捕獲reject錯誤,不寫catch會報錯
function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('reject');
    }, ms);
  });
}
async function asyncPrint(value, ms) {
  timeout(ms)
    .then(res => {
      return res;
    })
    .catch(error => {
      return Promise.reject(
        '返回reject錯誤,被後面的catct捕獲::' + error
      );
    })
    .catch(error => {
      console.log(error);
    });
}
asyncPrint('hello world', 1000);

Promise.all()

Promise.all()方法用於將多個Promise實例包裝成一個新的Promise實例,接收一個數組做爲參數。

var p = Promise.all([p1,p2,p3]);

如上例子,p1/p2/p3都是promise對象,p的狀態由他們共同決定:

1、只有當p1/p2/p3都變成Fulfilled時,p的狀態纔會變成Fulfilled,p1/p2/p3的返回值組成一個數組,傳遞給p的回調函數

2、只要p1/p2/p3有一個變成Rejected,p的狀態就會變成Rejected,此時第一個變成Rejected的實例的返回值會傳遞給p的回調函數

TIPS:如果p1/p2/p3自身定義了catch方法,那麼它被rejected時並不會觸發Promise.all()的catch方法,如下:

var p1 = new Promise((resolve,reject) => {
    resolve();
})
.then(value => value)
.catch(e => e);
var p2 = new Promise((resolve,reject) => {
    throw new Error('報錯了');
})
.then(value => value)
.catch(e => e);
var p = Promise.all([p1,p2])
.then(value => console.log(value))
.catch(e => console.log(e))
//['hello',Error:報錯了]

以上代碼:p1會resolved,p2首先會rejected,但是p2有自己的catch方法,該方法返回一個新的Promise實例,p2實際上指向的是這個實例,該實例執行完catch後也會變成resolved,導致p對象裏的兩個實例都會resolved,因此會調用p對象裏的then方法指定的回調函數,而不是catch方法

Promise.resolve()、Promise.reject():

有時需要將現有對象轉化爲Promise對象,以上兩個方法返回一個狀態爲resolve或reject的promise對象。

創建一個Promise的類

class PromiseNew {
  constructor(executer) {
    //構造函數constructor裏面是個執行器
    this.status = 'pending'; //默認的狀態 pending
    this.value = undefined; //成功的值默認undefined
    this.reason = undefined; //失敗的值默認undefined
    //狀態只有在pending時候才能改變
    let resolveFn = value => {
      //判斷只有等待時才能resolve成功
      if (this.status === 'pending') {
        this.status = 'resolve';
        this.value = value;
      }
    };
    //判斷只有等待時才能reject失敗
    let rejectFn = reason => {
      if (this.status === 'pending') {
        this.status = 'reject';
        this.reason = reason;
      }
    };
    try {
      //把resolve和reject兩個函數傳給執行器executer
      executer(resolveFn, rejectFn);
    } catch (e) {
      rejectFn(e); //失敗的話進catch
    }
  }
  then(onFufilled, onReject) {
    //如果狀態成功調用onFufilled
    if (this.status === 'resolve') {
      onFufilled(this.value);
    }
    //如果狀態失敗調用onReject
    if (this.status === 'reject') {
      onReject(this.reason);
    }
  }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章