日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理

發(fā)布時間:2023/12/2 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

整體流程的介紹

  • 整體流程的介紹

  • 1. 定義整體結構

  • 2. 實現(xiàn)Promise構造函數(shù)

  • 3. 實現(xiàn)then方法

  • 3.實現(xiàn)catch方法

  • 4. 實現(xiàn)Promise.resolve

  • 5.實現(xiàn)Promise.reject

  • 6.實現(xiàn)Promise.all

  • 7.實現(xiàn)Promise.race

文章會配合例子來講解為什么要這么實現(xiàn),盡我所能講得粗俗易懂。有什么不理解或建議,歡迎下方評論。項目源碼已經(jīng)放到 github,順手點個star唄:https://github.com/Sunny-lucking/howToBuildMyPromise

1. 定義整體結構

  • 先寫出構造函數(shù),將Promise向外暴露
  • /*
    自定義Promise函數(shù)模塊:IIFE
    ?*/

    (function?(window)?{
    ????/*
    ????Promise構造函數(shù)
    ????executor:執(zhí)行器函數(shù)
    ?????*/
    ????function?Promise(executor)?{

    ????}

    ????//?向外暴露Promise
    ????window.Promise?=?Promise
    })()

  • 添加Promise原型對象上的方法
  • ?/*
    ????Promise原型對象的then
    ????指定一個成功/失敗的回調函數(shù)
    ????返回一個新的promise對象
    ?????*/
    ????Promise.prototype.then?=?function(onResolved,onRejected){

    ????}

    ????/*
    ????Promise原型對象的.catch
    ????指定一個失敗的回調函數(shù)
    ????返回一個新的promise對象
    ?????*/
    ????Promise.prototype.catch?=?function(onRejected){

    ????}
  • 添加Promise函數(shù)對象上的方法
  • /*
    ????Promise函數(shù)對象的resovle方法
    ????返回一個指定結果的promise對象
    ?????*/
    ????Promise.resolve?=?function(value){

    ????}

    ????/*
    ????Promise函數(shù)對象的reject方法
    ????返回一個指定reason的失敗狀態(tài)的promise對象
    ????*/
    ????Promise.reject?=?function(value){

    ????}

    ????/*
    ????Promise函數(shù)對象的all方法
    ????返回一個promise對象,只有當所有promise都成功時返回的promise狀態(tài)才成功
    ????*/
    ????Promise.all?=?function(0value){

    ????}

    ????/*
    ????Promise函數(shù)對象的race方法
    ????返回一個promise對象,狀態(tài)由第一個完成的promise決定
    ????*/
    ????Promise.race?=?function(value){

    ????}

    通過上面的注釋可以知道。不管是Promise原型對象上的方法還是Promise函數(shù)對象上的方法 ,它們的執(zhí)行結果都將返回一個Promise對象

    2. 實現(xiàn)Promise構造函數(shù)

    我們看看我們是怎么使用Promise的

    const?promiseA?=?new?Promise(?(resolve,reject)?=>?{
    ????resolve(777);
    });
  • 我們傳入了一個函數(shù),而且這個函數(shù)被立即執(zhí)行,不僅如此,這個函數(shù)還會立即執(zhí)行resolve和reject。說明構造函數(shù)里有resolve和reject方法。因此我們可以初步實現(xiàn):
  • ????/*
    ????Promise構造函數(shù)
    ????executor:執(zhí)行器函數(shù)
    ?????*/
    ????function?Promise(executor)?{

    ????????function?resovle()?{

    ????????}
    ????????function?reject()?{

    ????????}

    ????????//?立即同步執(zhí)行executor
    ????????executor(resovle,reject)
    ????}

  • 每個promise都有一個狀態(tài)可能為pending或resolved,rejected。而且初始狀態(tài)都為pending。因此需要添加個status來表示當前promise的狀態(tài).。并且每個promise有自己的data。
  • function?Promise(executor)?{

    ????????var?self?=?self
    ????????新增代碼
    ????????self.status?=?'pending'?//?給promise對象指定status屬性,初始值為pending
    ????
    ????????self.data?=?undefined?//?給promise對象指定一個存儲結果的data

    ????????function?resovle()?{

    ????????}
    ????????function?reject()?{

    ????????}

    ????????//?立即同步執(zhí)行executor
    ????????executor(resovle,reject)
    ????}

    此外,當我們這樣使用Promise的時候,

    //?例1
    var?promise?=?new?Promise((resovle,reject)=>{
    ????
    })

    promise.then(resolve=>{},reject=>{})

    這時執(zhí)行到then,因為我們傳入的立即執(zhí)行函數(shù)沒有執(zhí)行resolve或者reject,所以promise的狀態(tài)還是pending,這時要把then里面的回調函數(shù)保存起來,所以需要個callbacks數(shù)組

    function?Promise(executor)?{

    ????????var?self?=?self

    ????????self.status?=?'pending'?//?給promise對象指定status屬性,初始值為pending
    ????????self.data?=?undefined?//?給promise對象指定一個存儲結果的data
    ????????新增代碼
    ????????self.callbacks?=?[]??//?每個元素的結構:{onResolved(){},onRejected(){}}


    ????????function?resovle()?{

    ????????}
    ????????function?reject()?{

    ????????}

    ????????//?立即同步執(zhí)行executor
    ????????executor(resovle,reject)
    ????}

    那 then函數(shù)是怎么把傳入的回調收集起來的。其實很簡單,就是判斷當前promise是否為pending狀態(tài),是的話,就把回調push到callbacks中。

    Promise.prototype.then?=?function(onResolved,onRejected){

    ????????var?self?=?this
    ????????
    ????????if(self.status?===?'pending'){
    ????????????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ????????????self.callbacks.push({
    ????????????????onResolved(){onResolved(self.data)},
    ????????????????onRejected(){onRejected(self.data)}
    ????????????})
    ????????}else?if(self.status?===?'resolved'){
    ????????}else{
    ????????}

    ????}
  • 在上面的例子1的基礎上,當我們執(zhí)行resovle(value)時,如例2
  • //?例2
    var?promise?=?new?Promise((resolve,reject)=>{
    ????setTimeout(function?()?{
    ????????resolve(1)
    ????})
    })

    promise.then(
    ????value=>{console.log(value)},
    ????err=>{console.log(err)}
    ????)

    此時代碼執(zhí)行情況是怎么樣的呢?

  • 先執(zhí)行new Promise里的代碼,然后發(fā)現(xiàn)個定時器,js線程將定時器交給定時器線程處理,2. 然后繼續(xù)執(zhí)行下面的代碼,發(fā)現(xiàn)是then,而且當前的promise還是pending的狀態(tài)。就把then里的回調函數(shù)放到callbacks中。
  • 5秒后定時器線程將定時器里的回調函數(shù)(也就是宏任務)放到消息隊列中,js線程在消息隊列里發(fā)現(xiàn)了這個宏任務,就把它拿來執(zhí)行。
  • 執(zhí)行這個宏任務,就執(zhí)行了resolve(1),此時promise的callbacks里的回調被執(zhí)行。并將當前promise狀態(tài)改為resolved。然后這個1也會被保存到當前promise對象中
  • 那怎么實現(xiàn)resolve呢?依舊上面的描述,就知道resovle的功能是執(zhí)行callbacks里的函數(shù),并保存data并將當前promise狀態(tài)改為resolved。所以我們可以這么實現(xiàn)

    function?resolve(value)?{
    ????//?將狀態(tài)改為resolved
    ????self.status?=?'resolved'
    ????//?保存value的值
    ????self.data?=?value

    ????//?如果有待執(zhí)行的callback函數(shù),立即異步執(zhí)行回調函數(shù)onResolved
    ????if?(self.callbacks.length>0){
    ????????self.callbacks.forEach(callbackObj=>{
    ????????????callbackObj.onResolved(value)
    ????????})
    ????}
    }
  • 我們還知道,promise的狀態(tài)只能改變一次,因此當執(zhí)行resolve的時候要判斷是不是promise是不是pending的狀態(tài),否則是不能執(zhí)行的
  • function?resolve(value)?{
    ????//?如果當前狀態(tài)不是pending,則不執(zhí)行
    ????if(this.status?!==?'pending'){
    ????????return?
    ????}
    ????//?將狀態(tài)改為resolved
    ????this.status?=?'resolved'
    ????//?保存value的值
    ????this.data?=?value

    ????//?如果有待執(zhí)行的callback函數(shù),立即異步執(zhí)行回調函數(shù)onResolved
    ????if?(this.callbacks.length>0){
    ????????setTimeout(()=>{
    ????????????this.callbacks.forEach(callbackObj=>{?A
    ????????????????callbackObj.onResolved(value)
    ????????????})
    ????????})
    ????}
    }
  • 異曲同工之妙的是reject方法也是這個道理,因此這里無需贅述
  • function?reject(value)?{
    ????//?如果當前狀態(tài)不是pending,則不執(zhí)行
    ????if(self.status?!==?'pending'){
    ????????return
    ????}
    ????//?將狀態(tài)改為rejected
    ????self.status?=?'rejected'
    ????//?保存value的值
    ????self.data?=?value

    ????//?如果有待執(zhí)行的callback函數(shù),立即異步執(zhí)行回調函數(shù)onResolved
    ????if?(self.callbacks.length>0){
    ??????self.callbacks.forEach(callbackObj=>{
    ??????????callbackObj.onRejected(value)
    ??????})
    ????}
    }
  • 我們又知道,當在執(zhí)行executor的時候,如果執(zhí)行異常的話,這個promise的狀態(tài)會直接執(zhí)行reject方法。例如
  • //?例?3
    var?promise?=?new?Promise((resolve,reject)=>{

    ??? error;執(zhí)行到這里出錯了

    ????setTimeout(function?()?{
    ????????resolve(1)
    ????})
    })

    要實現(xiàn)這個功能,我們可以在executor外讓try catch來捕獲

    try{
    ????//?立即同步執(zhí)行executor
    ????executor(resolve,reject)
    }catch?(e)?{?//?如果執(zhí)行器拋出異常,promise對象變?yōu)閞ejected狀態(tài)
    ????reject(e)
    }

    好了,現(xiàn)在測試下

    ?//?例4
    ?let?promise?=?new?Promise((resolve,reject)=>{
    ????????
    ????????setTimeout(function?()?{
    ????????????resolve(1)
    ????????????//reject(1)
    ????????},100)
    ????})

    ????promise.then(
    ????????value=>{
    ????????????console.log("onResolved:",value);
    ????????},
    ????????reason=>{
    ????????????console.log("onRejected:",reason);
    ????????}
    ????)

    發(fā)現(xiàn)成功。成功輸出onResolved:1

    3. 實現(xiàn)then方法

    我們在上面簡單的實現(xiàn)了當前promise為pending狀態(tài)的情況,如:

    Promise.prototype.then?=?function(onResolved,onRejected){

    ????var?self?=?this

    ????if(self.status?===?'pending'){
    ????????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ????????self.callbacks.push({
    ????????????onResolved(){onResolved(self.data)},
    ????????????onRejected(){onRejected(self.data)}
    ????????})
    ????}else?if(self.status?===?'resolved'){
    ????}else{
    ????}

    }

    那其他情況呢?

    執(zhí)行到then時,promise可能會是pending狀態(tài),此時就要把then里的回調函數(shù)保存起來,也可能會是resolved或者rejected狀態(tài),此時就不用把回調保存起來,直接執(zhí)行onResolved或onRejected方法。注意是異步執(zhí)行。而且是做為微任務的,這里我們簡單的用setTimeout來實現(xiàn)就好了。

    Promise.prototype.then?=?function(onResolved,onRejected){

    ??var?self?=?this

    ??if(self.status?===?'pending'){
    ??????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ??????self.callbacks.push({
    ??????????onResolved(){onResolved(self.data)},
    ??????????onRejected(){onRejected(self.data)}
    ??????})
    ??}else?if(self.status?===?'resolved'){
    ??????setTimeout(()=>{
    ??????????onResolved(self.data)
    ??????})
    ??}else{
    ??????setTimeout(()=>{
    ??????????onResolved(self.data)
    ??????})
    ??}

    }

    而且我們知道,執(zhí)行完then是要返回一個新的promise的,而新的promise的狀態(tài)則由當前then的執(zhí)行結果來確定。

    ?Promise.prototype.then?=?function(onResolved,onRejected){

    ????var?self?=?this

    ????return?new?Promise((resolve,reject)=>{
    ????????if(self.status?===?'pending'){
    ????????????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ????????????self.callbacks.push({
    ????????????????onResolved(){onResolved(self.data)},
    ????????????????onRejected(){onRejected(self.data)}
    ????????????})
    ????????}else?if(self.status?===?'resolved'){
    ????????????setTimeout(()=>{
    ????????????????onResolved(self.data)
    ????????????})
    ????????}else{
    ????????????setTimeout(()=>{
    ????????????????onResolved(self.data)
    ????????????})
    ????????}
    ????})

    }

    當 當前的promise狀態(tài)為resolved的時候,則執(zhí)行then的時候,會執(zhí)行第二個判斷語句

    則當前執(zhí)行第二個判斷語句的時候會出現(xiàn)三種情況

  • 如果then里的回調函數(shù)返回的不是promise,return的新promise的狀態(tài)是則是resolved,value就是返回的值。例如:
  • //?例5
    let?promise?=?new?Promise((resolve,reject)=>{
    ????resolve(1)
    })

    promise.then(
    ????value=>{
    ????????return?value?//返回的不是promise,是value
    ????}
    )

    因此,我們可以這樣實現(xiàn)

    Promise.prototype.then?=?function(onResolved,onRejected){

    ????var?self?=?this

    ????return?new?Promise((resolve,reject)=>{
    ????????if(self.status?===?'pending'){
    ????????????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ????????????self.callbacks.push({
    ????????????????onResolved(){onResolved(self.data)},
    ????????????????onRejected(){onRejected(self.data)}
    ????????????})
    ????????}else?if(self.status?===?'resolved'){
    ????????????修改代碼
    ????????????setTimeout(()=>{
    ????????????????const?result?=?onResolved(self.data)
    ????????????????if?(result?instanceof?Promise){

    ????????????????}?else?{
    ????????????????// 1. 如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ????????????????????resolve(result)
    ????????????????}
    ????????????})
    ????????}else{
    ????????????setTimeout(()=>{
    ????????????????onResolved(self.data)
    ????????????})
    ????????}
    ????})

    }

    簡單解釋下:

    執(zhí)行onResolved(self.data),其實就是執(zhí)行例子中的下面這個回調函數(shù)

    value=>{
    ????????return?value?//返回的不是promise,是value
    ????}

    那么這個回調函數(shù)返回了value。就把value傳入resolve函數(shù),resolve函數(shù)將當前新的promise的狀態(tài)改為resolved,同時將value保存到當前新的promise的data中。

  • 如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果,如代碼所示,我們返回一個新的promise。如果這個promise執(zhí)行了resolve,返回的新的promise的狀態(tài)則是resolved的。否則為rejected
  • //?例6
    let?promise?=?new?Promise((resolve,reject)=>{
    ????resolve(1)
    })

    promise.then(
    ????value=>{
    ????????return?new?Promise((resolve,reject)=>{
    ????????????resolve(2)
    ????????????//或者
    ????????????//reject(error)
    ????????})
    ????}
    )

    因此我們可以這樣實現(xiàn)

    Promise.prototype.then?=?function(onResolved,onRejected){

    ????var?self?=?this

    ????return?new?Promise((resolve,reject)=>{
    ????????if(self.status?===?'pending'){
    ????????????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ????????????self.callbacks.push({
    ????????????????onResolved(){onResolved(self.data)},
    ????????????????onRejected(){onRejected(self.data)}
    ????????????})
    ????????}else?if(self.status?===?'resolved'){
    ????????????setTimeout(()=>{
    ????????????????const?result?=?onResolved(self.data)
    ????????????????if?(result?instanceof?Promise){
    ????????????????????//?2.?如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果
    ????????????????????result.then(
    ????????????????????????value?=>?{resolve(value)},
    ????????????????????????reason?=>?{reject(reason)}
    ????????????????????)
    ????????????????}?else?{
    ????????????????????// 1. 如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ????????????????????resolve(result)
    ????????????????}
    ????????????})
    ????????}else{
    ????????????setTimeout(()=>{
    ????????????????onResolved(self.data)
    ????????????})
    ????????}
    ????})

    }

    在這里說明一下:

    result.then(
    ????value?=>?{resolve(value)},
    ????reason?=>?{reject(reason)}
    )

    由于我們在例6中執(zhí)行了then里的

    value=>{
    ????????return?new?Promise((resolve,reject)=>{
    ????????????resolve(2)
    ????????????//或者
    ????????????//reject(error)
    ????????})
    ????}

    則返回一個promise對象,這個promise對象可能為resolved狀態(tài)(執(zhí)行 resolve(2))也可能為rejected狀態(tài)(執(zhí)行reject(error))。

    將會導致value => {resolve(value)},這個回調函數(shù)的執(zhí)行或者reason => {reject(reason)}的執(zhí)行。

    因此會把即將返回的新的promise的data設置為value或者,reason。會把狀態(tài)設置為resolved或者rejected。

  • 如果執(zhí)行這段代碼的時候拋出錯誤,則返回的promise的狀態(tài)為rejected,我們可以用try catch來實現(xiàn)
  • setTimeout(()=>{
    ????try{
    ????????const?result?=?onResolved(self.data)
    ????????if?(result?instanceof?Promise){
    ????????????//?2.?如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果
    ????????????result.then(
    ????????????????value?=>?{resolve(value)},
    ????????????????reason?=>?{reject(reason)}
    ????????????)
    ????????}?else?{
    ????????????// 1. 如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ????????????resolve(result)
    ????????}
    ????}catch?(e)?{
    ??????//??3.如果執(zhí)行onResolved的時候拋出錯誤,則返回的promise的狀態(tài)為rejected
    ????????reject(e)
    ????}
    })

    異曲同工之妙的是當status === 'rejected',道理一樣

    ?setTimeout(()=>{
    ??????try{
    ??????????const?result?=?onRejected(self.data)
    ??????????if?(result?instanceof?Promise){
    ??????????????//?2.?如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果
    ??????????????result.then(
    ??????????????????value?=>?{resolve(value)},
    ??????????????????reason?=>?{reject(reason)}
    ??????????????)
    ??????????}?else?{
    ??????????????// 1. 如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ??????????????resolve(result)
    ??????????}
    ??????}catch?(e)?{
    ??????????//??3.如果執(zhí)行onResolved的時候拋出錯誤,則返回的promise的狀態(tài)為rejected
    ??????????reject(e)
    ??????}
    ??})

    到這里,我們發(fā)現(xiàn)當執(zhí)行resolve的時候,onResolved(self.data)和onRejected(self.data)執(zhí)行時也會跟上面一樣的結果,可以說執(zhí)行回調函數(shù)都要做以上判斷,因此我們要將

    ?self.callbacks.push({
    ????onResolved(){onResolved(self.data)},
    ????onRejected(){onRejected(self.data)}
    })

    改成

    if(self.status?===?'pending'){
    //?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    self.callbacks.push({
    ????onResolved(){
    ????????try{
    ????????????const?result?=?onResolved(self.data)
    ????????????if?(result?instanceof?Promise){
    ????????????????//?2.?如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果
    ????????????????result.then(
    ????????????????????value?=>?{resolve(value)},
    ????????????????????reason?=>?{reject(reason)}
    ????????????????)
    ????????????}?else?{
    ????????????????// 1. 如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ????????????????resolve(result)
    ????????????}
    ????????}catch?(e)?{
    ????????????//??3.如果執(zhí)行onResolved的時候拋出錯誤,則返回的promise的狀態(tài)為rejected
    ????????????reject(e)
    ????????}
    ????},

    到此,我們發(fā)現(xiàn),相同的代碼太多了,因此有必要封裝一下

    ?function?handle(callback)?{
    ????try{
    ????????const?result?=?callback(self.data)
    ????????if?(result?instanceof?Promise){
    ????????????//?2.?如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果
    ????????????result.then(
    ????????????????value?=>?{resolve(value)},
    ????????????????reason?=>?{reject(reason)}
    ????????????)
    ????????}?else?{
    ????????????//?1.?如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ????????????resolve(result)
    ????????}
    ????}catch?(e)?{
    ????????//??3.如果執(zhí)行onResolved的時候拋出錯誤,則返回的promise的狀態(tài)為rejected
    ????????reject(e)
    ????}
    }

    這樣以來就清爽了很多

    ???Promise.prototype.then?=?function(onResolved,onRejected){

    ????????var?self?=?this

    ????????return?new?Promise((resolve,reject)=>{
    ???????????/*
    ????????????調用指定回調函數(shù)的處理,根據(jù)執(zhí)行結果。改變return的promise狀態(tài)
    ?????????????*/
    ????????????function?handle(callback)?{
    ????????????????try{
    ????????????????????const?result?=?callback(self.data)
    ????????????????????if?(result?instanceof?Promise){
    ????????????????????????//?2.?如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果
    ????????????????????????result.then(
    ????????????????????????????value?=>?{resolve(value)},
    ????????????????????????????reason?=>?{reject(reason)}
    ????????????????????????)
    ????????????????????}?else?{
    ????????????????????????// 1. 如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ????????????????????????resolve(result)
    ????????????????????}
    ????????????????}catch?(e)?{
    ????????????????????//??3.如果執(zhí)行onResolved的時候拋出錯誤,則返回的promise的狀態(tài)為rejected
    ????????????????????reject(e)
    ????????????????}
    ????????????}
    ????????????if(self.status?===?'pending'){
    ????????????????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ????????????????self.callbacks.push({
    ????????????????????onResolved(){
    ????????????????????????handle(onResolved)
    ????????????????????},
    ????????????????????onRejected(){
    ????????????????????????handle(onRejected)
    ????????????????????}
    ????????????????})
    ????????????}else?if(self.status?===?'resolved'){
    ????????????????setTimeout(()=>{
    ????????????????????handle(onResolved)
    ????????????????})
    ????????????}else{?//?當status?===?'rejected'
    ????????????????setTimeout(()=>{
    ????????????????????handle(onRejected)
    ????????????????})
    ????????????}
    ????????})

    ????}

    另外,我們還知道,promise會發(fā)生值傳透,例如


    let?promsie?=?new?Promise((resolve,reject)=>{
    ????resolve(1)
    })
    promsie
    ??.then(2)
    ??.then(3)
    ??.then(value?=>console.log(value))

    運行結果:1

    解釋:.then 或者 .catch 的參數(shù)期望是函數(shù),傳入非函數(shù)則會發(fā)生值穿透。值傳透可以理解為,當傳入then的不是函數(shù)的時候,這個then是無效的。而實際原理上其實是當then中傳入的不算函數(shù),則這個then返回的promise的data,將會保存上一個的promise.data。這就是發(fā)生值穿透的原因。而且每一個無效的then所返回的promise的狀態(tài)都為resolved

    因此,要實現(xiàn)直傳透這個特性,我們可以這樣實現(xiàn)

    添加這兩句來判斷要不要發(fā)生值傳透

    onResolved?=?typeof?onResolved?===?'function'??onResolved:?value?=>?value
    onRejected?=?typeof?onRejected?===?'function'??onRejected:?reason?=>?{throw?reason}

    實際上就是改寫,如果傳入的不是函數(shù),那就忽略那個傳入值,自己再寫一個函數(shù)。這個函數(shù)的執(zhí)行結果將返回上一個promise的data

    Promise.prototype.then?=?function(onResolved,onRejected){
    ????onResolved?=?typeof?onResolved?===?'function'??onResolved:?value?=>?value
    ????onRejected?=?typeof?onRejected?===?'function'??onRejected:?reason?=>?{throw?reason}
    ????var?self?=?this

    ????return?new?Promise((resolve,reject)=>{

    ????????/*
    ????????調用指定回調函數(shù)的處理,根據(jù)執(zhí)行結果。改變return的promise狀態(tài)
    ?????????*/
    ????????function?handle(callback)?{
    ????????????try{
    ????????????????const?result?=?callback(self.data)
    ????????????????if?(result?instanceof?Promise){
    ????????????????????//?2.?如果回調函數(shù)返回的是promise,return的promise的結果就是這個promise的結果
    ????????????????????result.then(
    ????????????????????????value?=>?{resolve(value)},
    ????????????????????????reason?=>?{reject(reason)}
    ????????????????????)
    ????????????????}?else?{
    ????????????????????// 1. 如果回調函數(shù)返回的不是promise,return的promise的狀態(tài)是resolved,value就是返回的值。
    ????????????????????resolve(result)
    ????????????????}
    ????????????}catch?(e)?{
    ????????????????//??3.如果執(zhí)行onResolved的時候拋出錯誤,則返回的promise的狀態(tài)為rejected
    ????????????????reject(e)
    ????????????}
    ????????}
    ????????if(self.status?===?'pending'){
    ????????????//?promise當前狀態(tài)還是pending狀態(tài),將回調函數(shù)保存起來
    ????????????self.callbacks.push({
    ????????????????onResolved(){
    ????????????????????handle(onResolved)
    ????????????????},
    ????????????????onRejected(){
    ????????????????????handle(onRejected)
    ????????????????}
    ????????????})
    ????????}else?if(self.status?===?'resolved'){
    ????????????setTimeout(()=>{
    ????????????????handle(onResolved)
    ????????????})
    ????????}else{?//?當status?===?'rejected'
    ????????????setTimeout(()=>{
    ????????????????handle(onRejected)
    ????????????})
    ????????}
    ????})

    }

    3.實現(xiàn)catch方法

    catch方法的作用跟then里的第二歌回調函數(shù)一樣,因此我們可以這樣來實現(xiàn)

    Promise.prototype.catch?=?function(onRejected){
    ????return?this.then(undefined,onRejected)
    }

    我的天啊,居然這么簡單

    4. 實現(xiàn)Promise.resolve

    我們都知道,Promise.resolve方法可以傳三種值

  • 不是promise
  • 成功狀態(tài)的promise
  • 失敗狀態(tài)的promise

  • ????Promise.resolve(1)
    ????Promise.resolve(Promise.resolve(1))
    ????Promise.resolve(Promise.reject(1))

    實際上跟實現(xiàn)上面的then時有點像

    Promise.resolve?=?function(value){
    ??return?new?Promise((resolve,reject)=>{
    ??????if?(value?instanceof?Promise){
    ??????????//?如果value?是promise
    ??????????value.then(
    ??????????????value?=>?{resolve(value)},
    ??????????????reason?=>?{reject(reason)}
    ??????????)
    ??????}?else{
    ??????????//?如果value不是promise
    ??????????resolve(value)
    ??????}

    ??}

    }

    5.實現(xiàn)Promise.reject

    實現(xiàn)這個比較簡單,返回一個狀態(tài)為rejected的promise就好了

    /*
    Promise函數(shù)對象的reject方法
    返回一個指定reason的失敗狀態(tài)的promise對象
    */
    Promise.reject?=?function(reason){
    ????return?new?Promise((resolve,reject)=>{
    ????????reject(reason)
    ????})
    }

    6.實現(xiàn)Promise.all

    我們知道,這個方法會返回一個promise

    ????/*
    ????Promise函數(shù)對象的all方法
    ????返回一個promise對象,只有當所有promise都成功時返回的promise狀態(tài)才成功
    ????*/
    ????Promise.all?=?function(promises){
    ????????return?new?Promise((resolve,reject)=>{
    ???????????
    ????????})
    ????}
    ??

    而這個promise的狀態(tài)由遍歷每個promise產(chǎn)生的結果決定

    ????/*
    ????Promise函數(shù)對象的all方法
    ????返回一個promise對象,只有當所有promise都成功時返回的promise狀態(tài)才成功
    ????*/
    ????Promise.all?=?function(promises){
    ????????return?new?Promise((resolve,reject)=>{
    ????????????//?遍歷promises,獲取每個promise的結果
    ????????????promises.forEach((p,index)=>{
    ????????????????
    ????????????})
    ????????})
    ????}

    有兩種結果:

  • 遍歷到有一個promise是reject狀態(tài),則直接返回的promise狀態(tài)為rejected
  • ?Promise.all?=?function(promises){
    ????????return?new?Promise((resolve,reject)=>{
    ????????????//?遍歷promises,獲取每個promise的結果
    ????????????promises.forEach((p,index)=>{
    ????????????????p.then(
    ????????????????????value?=>?{
    ????
    ????????????????????},
    ????????????????????reason?=>?{?//只要有一個失敗,return的promise狀態(tài)就為reject
    ????????????????????????reject(reason)
    ????????????????????}
    ????????????????)
    ????????????})
    ????????})
    ????}
  • 遍歷所有的promise的狀態(tài)都為resolved,則返回的promise狀態(tài)為resolved,并且還要每個promise產(chǎn)生的值傳遞下去
  • ???Promise.all?=?function(promises){
    ??????const?values?=?new?Array(promises.length)
    ??????var?resolvedCount?=?0?//計狀態(tài)為resolved的promise的數(shù)量
    ??????return?new?Promise((resolve,reject)=>{
    ??????????//?遍歷promises,獲取每個promise的結果
    ??????????promises.forEach((p,index)=>{
    ??????????????p.then(
    ??????????????????value?=>?{
    ??????????????????????//?p狀態(tài)為resolved,將值保存起來
    ??????????????????????values[index]?=?value
    ??????????????????????resolvedCount++;
    ??????????????????????//?如果全部p都為resolved狀態(tài),return的promise狀態(tài)為resolved
    ??????????????????????if(resolvedCount?===?promises.length){
    ??????????????????????????resolve(values)
    ??????????????????????}
    ??????????????????},
    ??????????????????reason?=>?{?//只要有一個失敗,return的promise狀態(tài)就為reject
    ??????????????????????reject(reason)
    ??????????????????}
    ??????????????)
    ??????????})
    ??????})
    ??}

    好像可以了,當其實這里還有一個問題,就是all傳進去的數(shù)組不一定都是promise對象,可能是這樣的

    all([p,2,3,p])

    因此需要把不是promise的數(shù)字包裝成promise

    ????Promise.all?=?function(promises){
    ????????const?values?=?new?Array(promises.length)
    ????????var?resolvedCount?=?0?//計狀態(tài)為resolved的promise的數(shù)量
    ????????return?new?Promise((resolve,reject)=>{
    ????????????//?遍歷promises,獲取每個promise的結果
    ????????????promises.forEach((p,index)=>{
    ????????????????Promise.resolve(p).then(
    ????????????????????value?=>?{
    ????????????????????????//?p狀態(tài)為resolved,將值保存起來
    ????????????????????????values[index]?=?value
    ????????????????????????resolvedCount++;
    ????????????????????????//?如果全部p都為resolved狀態(tài),return的promise狀態(tài)為resolved
    ????????????????????????if(resolvedCount?===?promises.length){
    ????????????????????????????resolve(values)
    ????????????????????????}
    ????????????????????},
    ????????????????????reason?=>?{?//只要有一個失敗,return的promise狀態(tài)就為reject
    ????????????????????????reject(reason)
    ????????????????????}
    ????????????????)
    ????????????})
    ????????})
    ????}

    7.實現(xiàn)Promise.race

    這個方法的實現(xiàn)要比all簡單很多

    ??/*
    ????Promise函數(shù)對象的race方法
    ????返回一個promise對象,狀態(tài)由第一個完成的promise決定
    ????*/
    ????Promise.race?=?function(promises){
    ????????return?new?Promise((resolve,reject)=>{
    ????????????//?遍歷promises,獲取每個promise的結果
    ????????????promises.forEach((p,index)=>{
    ????????????????Promise.resolve(p).then(
    ????????????????????value?=>?{
    ????????????????????????//?只要有一個成功,返回的promise的狀態(tài)九尾resolved
    ????????????????????????resolve(value)

    ????????????????????},
    ????????????????????reason?=>?{?//只要有一個失敗,return的promise狀態(tài)就為reject
    ????????????????????????reject(reason)
    ????????????????????}
    ????????????????)
    ????????????})
    ????????})
    ????}

    有什么不理解或建議,歡迎下方評論。項目源碼已經(jīng)放到github:https://github.com/Sunny-lucking/howToBuildMyPromise ?順手點個star唄

    去做一下題,看看是不是真的掌握了呢?【建議星星】要就來45道Promise面試題一次爽到底(1.1w字用心整理)

    之前可能會出現(xiàn)有些題不會做,而當你閱讀完這篇文章后,再去做,發(fā)現(xiàn)易如反掌。

    總結

    以上是生活随笔為你收集整理的定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。