深入理解promise

promise規(guī)范

規(guī)范-promise/A+ 術(shù)語(yǔ)

1.promise 一個(gè)有then方法的對(duì)象或函數(shù),行為符合本規(guī)范
2.thenable 一個(gè)定義了then方法的對(duì)象和函數(shù)
3.值,value 任何JavaScript的合法值
4.異常,exception throw語(yǔ)句拋出的值
5.拒絕原因,reason 一個(gè)標(biāo)示promise被拒絕原因的值

規(guī)范-promise/A+ 要求

promise的狀態(tài):

  • pending
  • fulfilled
  • rejected
    state:pending --- value --->state:fulfilled
    |-- reason--->state:rejected

then方法

const promise2 = promise1.then(onFulfilled,onRejected);

then方法的參數(shù)
  • 兩個(gè)函數(shù)參數(shù)
  • onFulfilled在promise完成后被調(diào)用,onRejected在promise被拒絕執(zhí)行后調(diào)用
  • 只被調(diào)用一次
    then方法的調(diào)用:可以調(diào)用多次
    then方法的返回值:promise
  1. onFulfilled不是函數(shù),promise1的狀態(tài)是fulfilled----state:fulfilled,value:同promise1
  2. onRejected不是函數(shù),promise1的狀態(tài)是rejected----state:rejected,reason:同promise1
  3. onFulfilled或者onRejected return x----進(jìn)入解析過(guò)程

promise解析過(guò)程

  • 抽象模型resolve(promise,x)
  • 如果promise和x指向相同的值
  • 如果x是一個(gè)promise
  • 如果x是一個(gè)對(duì)象或一個(gè)函數(shù)
  • 如果x不是對(duì)象也不是函數(shù)
function resolve(promise,x){
  if(x === promise){
    return reject(promise,new TypeError('cant be the same'));
  }
  if(isPromise(x)){
    if(x.state === 'pending'){
      return x.then(() => {
        resolve(promise,x.value);
      },() => {
        reject(promise,x.value);
      })
    }
    if(x.state == 'fulfilled'){
      return fulfill(promise,x.value);
    }
    if(x.state === 'rejected'){
      return reject(promise,x.value)
    }
  }else if(isObject(x) || isFunction(x)){
    let then;
    try{
      then = x.then;
    }catch(e){
      return reject(promise,e);
    }
    if(isFunction(then)){
      let isCalled = false;
      try{
        then.call(x,function resolvePromise(y){
          if(isCalled){
            return;
          }
          isCalled = true;
          resolve(promise,y);
        },function rejectPromise(r){
          if(isCalled){
            return;
          }
          isCalled = true;
          reject(promise,r)
        });
      }catch(e){
        if(!ifCalled){
          return reject(promise,e);
        }
      }
    }else{
      return fulfill(promise,x)
    }
  }else{
    return fulfill(promise,x)
  }
}

ES6 promise API

Promise構(gòu)造函數(shù)

構(gòu)造函數(shù)

new Promise(function(resolve,reject){
  //rosolve(value)
  //reject(reason)
})

說(shuō)明

  • 函數(shù)作為參數(shù)
  • resolve函數(shù)將promise狀態(tài)從pending變成resolved(fulfilled)
  • reject函數(shù)將promise狀態(tài)從pending變成rejected

靜態(tài)方法

  • Promise.resolve(param) : 等同于 new Promise(function(resolve,reject){resolve(param)})
  • Promise.reject(param) : 等同于 new Promise(function(resolve,reject){reject(param)})
  • Promise.all([p1,...,pn) : 輸入一組promise返回一個(gè)新的promise,全部promise都是fulfilled結(jié)果才是fulfilled狀態(tài)
  • Promise.allSettled([p1,...,pn) : 輸入一組promise返回一個(gè)新的promise,全部promise狀態(tài)改變后結(jié)果promise變成fulfilled狀態(tài)
  • Promise.race([p1,...,pn) : 輸入一組promise返回一個(gè)新的promise,結(jié)果promise的狀態(tài)跟隨第一個(gè)變化的promise狀態(tài)

實(shí)例方法

  • promise.then(onFulfilled,onRejected) : promise狀態(tài)改變之后的回調(diào),返回新的promise對(duì)象
  • promise.catch(function(reason){}) : t同promise.then(null,onRejected),promise狀態(tài)改為rejected的回調(diào)
  • promise.finally(function(reason){//test} : 同promise.then(function(){//test},function(){//test}),不管promise狀態(tài)如何都會(huì)執(zhí)行

注意點(diǎn)

  • then、catch返回的promise是新的promise,不是原來(lái)的promise.
  • Promise對(duì)象的錯(cuò)誤會(huì)“冒泡”,直到被捕獲為止,錯(cuò)誤會(huì)被下一個(gè)catch語(yǔ)句捕獲。

Promise實(shí)踐

  • 不要忘記catch捕捉錯(cuò)誤
  • then方法中使用return
  • 傳遞函數(shù)給then方法
  • 不要把promise寫(xiě)成嵌套

題目

  • 3秒之后亮一次紅燈,再過(guò)2秒亮一次綠燈,再過(guò)1秒亮一次黃燈,用promise實(shí)現(xiàn)多次交替亮燈的效果

拆解:

  1. 多少秒后亮某個(gè)顏色的燈
  2. 順序亮一批燈
  3. 循環(huán)順序亮一批燈
function light(color,second){
  return new Promise(function(resolve,reject){
    setTimeout(function(){
      console.log(color);
      resolve();
    },second * 1000);
  });
}

//[{color:xx,second:xx}]
function orderLights(list){
  let promise = Promise.resolve();
  list.forEach(item => {
    promise = promise.then(function(){
      return light(item.color,item.second);
    });
  });
  promise.then(function(){
    return orderLights(list);
  })
}

orderLights([{
  color:'red',
  second:3,
},{
  color:'green',
  second:3,
},{
  color:'yellow',
  second:3,
}]);

課后習(xí)題

  • 根據(jù)Promise/A+規(guī)范實(shí)現(xiàn)promise,使用promises-aplus/promises-tests插件驗(yàn)證
  • 找一些promise的面試題
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容