promise實(shí)現(xiàn)

Promises/A+規(guī)范文檔
Promises/A+規(guī)范文檔中文翻譯

Promise標(biāo)準(zhǔn):

  • 擁有一個(gè)then方法
  • fulfill 成功時(shí)的操作,即resolve
  • reject 失敗時(shí)的操作
  • padding 等待

一個(gè)簡(jiǎn)單的promise流程

function Promise(fn) {
    var value = null
    var callback = []
    this.then = function(onFulfilled){
      callbacks.push(onFulfilled)
    }
    function resolve(value){
      callbacks.forEach(function(callback){
       value = callback(value)
      })
    }
    fn(resolve)
}
 new Promise(
    function(resolve){
      setTimeout(()=>{
        console.log(123)
        return resolve(6)
      },1000)
    }
).then(
    (v)=>{
      console.log('1',v)
      return v
    }     
)
// 一秒鐘后
// 123
// 1 6

上述代碼很簡(jiǎn)單,大家肯定都能看得懂懂更。

  1. 將then方法掛載到callbacks隊(duì)列
  2. 創(chuàng)建的promise實(shí)例傳入的函數(shù)會(huì)被賦予resolve參數(shù)富玷,resolve能啟動(dòng)callbacks隊(duì)列耘斩,當(dāng)異步函數(shù)執(zhí)行完時(shí)磁携,將結(jié)果給resolve酌摇,resolve就能帶著這個(gè)結(jié)果啟動(dòng)callbacks轧简,執(zhí)行then函數(shù)驰坊。

不難發(fā)現(xiàn),then是需要鏈?zhǔn)秸{(diào)用的哮独,總所周知鏈?zhǔn)秸{(diào)用也很簡(jiǎn)單拳芙,只需要添加 return this即可
修改如下

this.then = function (onFulfilled) {
    callbacks.push(onFulfilled);
    return this;
};

這個(gè)時(shí)候我們刪掉定時(shí)器,突然發(fā)現(xiàn)皮璧, 123正常輸出舟扎,但是1 6并沒有輸出,為什么呢悴务?睹限?這是因?yàn)椋潭际峭窖堕埽?dāng)我們執(zhí)行resolve的時(shí)候羡疗,then還沒有掛載到隊(duì)列上面。根據(jù)js執(zhí)行機(jī)制别洪,我們可以加一個(gè)setTimeout 叨恨,setTimeout是異步函數(shù),屬于宏任務(wù)挖垛,會(huì)放在任務(wù)最后痒钝。將resolve中執(zhí)行回調(diào)的邏輯放在任務(wù)隊(duì)列末尾,以保證resolve時(shí)晕换,then方法已經(jīng)全部掛載完畢即可午乓。

function resolve(value) {
    setTimeout(function() {
        callbacks.forEach(function (callback) {
            value = callback(value);
        });
    }, 0)
}

這是個(gè)時(shí)候可能我們又發(fā)現(xiàn)

new Promise(
      function(resolve){
        setTimeout(()=>{
          console.log(123)
          return resolve(6)
        },1000)         
      }
    ).then(
      (v)=>{
        console.log('1',v)
        return v
      }     
    ).then(
        setTimeout((v)=>{
          console.log('3', v)
      },1000)
   )
// 123
// 1 undefined
// 1  6
// Uncaught TypeError: callback is not a function

我們需要優(yōu)化resolve方法

function resolve(value) {
      setTimeout(()=>{
        callbacks.forEach(function (callback) {
          if (typeof callback === 'function') {
            value = callback(value)
           }
        });
      },0)              
    }

加入狀態(tài)

pending,fulfilled,rejected

function Promise(fn) {
    let value = null
    let callbacks = []
    let state = 'pending'
    this.then = function (onFulfilled) {
      if(state==='pending'){
        callbacks.push(onFulfilled);
        return this;
      }
      onFulfilled(value)
      return this             
    };
    function resolve(value) {
      state = 'fulfilled'
      setTimeout(()=>{
        callbacks.forEach(function (callback) {
          if (typeof callback === 'function') {
            value = callback(value);
            }
        });
      },0)              
    }
    fn(resolve);
}
 function Promise1(fn) {
      var state = 'pending'
      var value = null
      var callbacks = []

      this.then = function (onFulfilled, onRejected) {
        return new Promise1(function (resolve, reject) {
          handle({
            onFulfilled: onFulfilled || null,
            onRejected: onRejected || null,
            resolve: resolve,
            reject: reject
          })
        })
      }
      
      function handle(callback){
        console.log(state)
        if(state === 'pending'){
          callbacks.push(callback)
          return
        }
        console.log(state)
        var cb = state === 'fulfilled' ? callback.onFulfilled : callback.onRejected
        var ret

        if(cb === null){
          cb = state === 'fulfilled' ? callback.onFulfilled : callback.onRejected
          cb(value)
          return
        }
        try{
          ret = cb(value)
          console.log('ret',ret)
          callback.resolve(ret)
        }catch(e){
          callback.reject(e)
        }
      }

      function resolve(newValue){
        if(newValue && (typeof newValue === 'object' || typeof newValue === 'function')){
          console.log('function')
          var then = newValue.then
          if(typeof then ==='function'){
            then.call(newValue,resolve,reject)
            return
          }
        }
        console.log('nofunction')

        state = 'fulfilled'
        value = newValue
        execute()
      }

      function  reject(reason){
        state = 'rejected'
        value = reason
        execute()
      }

      function execute(){
        setTimeout(function(){
          callbacks.forEach(function(callback){
            handle(callback)
          })
        },0)
      }

      fn(resolve,reject)
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市闸准,隨后出現(xiàn)的幾起案子益愈,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒸其,死亡現(xiàn)場(chǎng)離奇詭異敏释,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)摸袁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門钥顽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人靠汁,你說我怎么就攤上這事蜂大。” “怎么了蝶怔?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵奶浦,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我踢星,道長(zhǎng)澳叉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任沐悦,我火速辦了婚禮成洗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘藏否。我一直安慰自己瓶殃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布秕岛。 她就那樣靜靜地躺著碌燕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪继薛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天愈捅,我揣著相機(jī)與錄音遏考,去河邊找鬼。 笑死蓝谨,一個(gè)胖子當(dāng)著我的面吹牛灌具,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播譬巫,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼咖楣,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了芦昔?” 一聲冷哼從身側(cè)響起诱贿,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后珠十,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體料扰,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年焙蹭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晒杈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孔厉,死狀恐怖拯钻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撰豺,我是刑警寧澤粪般,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站郑趁,受9級(jí)特大地震影響刊驴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寡润,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一捆憎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梭纹,春花似錦躲惰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绍载,卻和暖如春诡宗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背击儡。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國打工塔沃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阳谍。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓蛀柴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親矫夯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鸽疾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容