手寫promise

一i:初始化三種狀態(tài):
1;待定狀態(tài)

      const PENDING = 'pending'

2:以實(shí)現(xiàn) 成功狀態(tài)

       const FULFILLED = 'fulfilled'

3:失敗狀態(tài)

   const REJECTED = 'rejected'

二:實(shí)現(xiàn)reject()和resolve()
/ 以構(gòu)造函數(shù)的形式實(shí)現(xiàn)

                       class MyPromise {

               constructor(executor) {
// 利用 try/catch 捕獲錯(cuò)誤
try {
  executor(this.resolve, this.reject)
} catch (error) {
  this.reject(error)
}
                             }
                           // 定義 Promise 初始狀態(tài)為 PENDING
                            status = PENDING
                            // resolve 后返回的數(shù)據(jù)
                             data = undefined
                             // reject 后返回的原因
                            reason = undefined
                            // 成功
                           resolve = data => {
                        // 一旦狀態(tài)改變炸卑,就不能再變
                   if (this.status !== PENDING) return
                                  // 更改狀態(tài)
                         this.status = FULFILLED
                  // 保存數(shù)據(jù)
                               this.data = data
                           }
                   // 失敗
               reject = reason => {
         // 一旦狀態(tài)改變痘番,就不能再變
if (this.status !== PENDING) return
// 更改狀態(tài)
this.status = REJECTED
// 保存原因
this.reason = reason
             }
   }

三:實(shí)現(xiàn)then

.then() 方法是 Promise 的核心之一巡雨,異步操作的成功或失敗版仔,都可以通過
.then() 添加的回調(diào)函數(shù)進(jìn)行處理。并且它將繼續(xù)返回一個(gè) Promise 對(duì)象馒吴,這樣可以通過多次調(diào)用
.then() 添加多個(gè)回調(diào)函數(shù)寺晌,它們會(huì)按照插入的順序執(zhí)行,形成鏈?zhǔn)秸{(diào)用(chaining)户魏。

                                      class MyPromise {

                                                / resolve 的回調(diào)函數(shù)列表
                                              successCallback = []
                                            // reject 的回調(diào)函數(shù)列表
                                          failureCallback = []
                                                   // 成功
                                      resolve = data => {
// 依次調(diào)用成功回調(diào)
while (this.successCallback.length) {
  this.successCallback.shift()(this.data)
}
                            }
                                       // 失敗
 reject = reason => {
// 依次調(diào)用失敗回調(diào)
while (this.failureCallback.length) {
  this.failureCallback.shift()(this.reason)
}
    }
                           // .then():處理 resolve 和 reject
                             then(onResolved = data => data /*設(shè)置默認(rèn)的成功回調(diào) */, onRejected) {
// 創(chuàng)建一個(gè)新的 Promise 并 return驶臊,以供鏈?zhǔn)秸{(diào)用
let promise = new MyPromise((resolve, reject) => {
  if (this.status === FULFILLED) {
    // 轉(zhuǎn)換為 異步執(zhí)行,用來獲取 新的 promise
    setTimeout(() => {
      try {
        let value = onResolved(this.data)
        // 判斷返回值是普通值還是 Promise
        resolvePromise(promise, value, resolve, reject)
      } catch (error) {
        reject(error)
      }
    }, 0)
  } else if (this.status === REJECTED) {
    setTimeout(() => {
      try {
        let value = onRejected(this.reason)
        resolvePromise(promise, value, resolve, reject)
      } catch (error) {
        reject(error)
      }
    }, 0)
  } else {
    // 將回調(diào)函數(shù)存入數(shù)組中等待被執(zhí)行
    this.successCallback.push(() => {
      setTimeout(() => {
        try {
          let value = onResolved(this.data)
          resolvePromise(promise, value, resolve, reject)
        } catch (error) {
          reject(error)
        }
      }, 0)
    })
    // 將回調(diào)函數(shù)存入數(shù)組中等待被執(zhí)行
    this.failureCallback.push(() => {
      setTimeout(() => {
        try {
          let value = onRejected(this.reason)
          resolvePromise(promise, value, resolve, reject)
        } catch (error) {
          reject(error)
        }
      }, 0)
    })
  }
})
return promise

}
}
第四步:實(shí)現(xiàn) .catch()
實(shí)現(xiàn) .then() 之后叼丑,.catch() 就會(huì)簡單很多关翎。事實(shí)上,.catch() 只是沒有給 fulfilled 狀態(tài)預(yù)留參數(shù)位置的 .then() 而已幢码,所以這里我們直接返回一個(gè)沒有成功回調(diào)函數(shù)的 .then() 即可笤休。

class MyPromise {
// .catch()
catch(onRejected) {
// 事實(shí)上 .catch() 只是沒有給 fulfilled 狀態(tài)預(yù)留參數(shù)位置的 .then()
return this.then(undefined, onRejected)
}
}
第五步:實(shí)現(xiàn) .finally()
有時(shí)候我們會(huì)在成功或失敗執(zhí)行相同的函數(shù),為了避免了同樣的語句需要在中各寫一次的情況症副,所以有了.finally() 方法店雅。也就是說,在 Promise 的結(jié)果無論是 fulfilled 或者是 rejected贞铣,.finally() 都會(huì)執(zhí)行指定的回調(diào)函數(shù)闹啦。但區(qū)別于 .then() 和 .catch(),.finally() 的回調(diào)函數(shù)中不接收任何參數(shù)

class MyPromise {
                                         // .finally()
  finally(callback) {
return this.then(
  data => {
    return MyPromise.resolve(callback().then(() => data))
  },
  err => {
    return MyPromise.resolve(callback()).then(() => {
      throw err
    })
  }
 )

}
}
第六步:實(shí)現(xiàn) Promise.all()
Promise.all() 方法主要用于集合多個(gè) Promise 的返回結(jié)果辕坝。

                                      class MyPromise {
                                    // Promise.all()
static all(iterable) {
// 記錄執(zhí)行次數(shù)
let times = 0
// 保存執(zhí)行結(jié)果
let result = []
// Promise.all() 會(huì)返回一個(gè) Promise
return new MyPromise((resolve, reject) => {
  // 記錄結(jié)果
  function addData(key, value) {
    times++
    result[key] = value
    times === iterable.length && resolve(result)
  }
  // 依次執(zhí)行窍奋,然后將結(jié)果保存到數(shù)組中
  iterable.forEach((element, index) => {
    // 判斷元素是否為 Promise 對(duì)象
    element instanceof MyPromise
      ? element.then(
          data => addData(index, data),
          err => reject(err) // 任何一個(gè) Promise 對(duì)象的 reject 被執(zhí)行都會(huì)立即 reject()
        )
      : addData(index, element) // 非 promise 的元素將被直接放在返回?cái)?shù)組中
  })
})

}
}
第七步:實(shí)現(xiàn) Promise.resolve(
Promise.resolve() 方法返回一個(gè)以給定值解析后的 Promise 對(duì)象。

class MyPromise {
// Promise.resolve()
static resolve(value) {
// 返回一個(gè)以給定值解析后的 Promise 對(duì)象
return value instanceof MyPromise
? value
: new MyPromise(resolve => resolve(value))
}
}

第八步:實(shí)現(xiàn) Promise.reject()
Promise.reject() 方法返回一個(gè)帶有拒絕原因的 Promise 對(duì)象酱畅。

                                      class MyPromise {
                                        // Promise.reject()
                                    static reject(error) {
return new MyPromise((resolve, reject) => {
  reject(error)
})

}
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末琳袄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纺酸,更是在濱河造成了極大的恐慌窖逗,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件餐蔬,死亡現(xiàn)場離奇詭異碎紊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)樊诺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門仗考,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人词爬,你說我怎么就攤上這事秃嗜。” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵痪寻,是天一觀的道長螺句。 經(jīng)常有香客問我,道長橡类,這世上最難降的妖魔是什么蛇尚? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮顾画,結(jié)果婚禮上取劫,老公的妹妹穿的比我還像新娘。我一直安慰自己研侣,他們只是感情好谱邪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庶诡,像睡著了一般惦银。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上末誓,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天扯俱,我揣著相機(jī)與錄音,去河邊找鬼喇澡。 笑死迅栅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晴玖。 我是一名探鬼主播读存,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呕屎!你這毒婦竟也來了让簿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤秀睛,失蹤者是張志新(化名)和其女友劉穎尔当,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體琅催,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡居凶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年虫给,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了藤抡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抹估,死狀恐怖缠黍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情药蜻,我是刑警寧澤瓷式,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布替饿,位于F島的核電站,受9級(jí)特大地震影響贸典,放射性物質(zhì)發(fā)生泄漏视卢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一廊驼、第九天 我趴在偏房一處隱蔽的房頂上張望据过。 院中可真熱鬧,春花似錦妒挎、人聲如沸绳锅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鳞芙。三九已至,卻和暖如春期虾,著一層夾襖步出監(jiān)牢的瞬間原朝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國打工彻消, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竿拆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓宾尚,卻偏偏與公主長得像丙笋,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子煌贴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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