成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

我能不能在不看別人怎么實(shí)現(xiàn)promise的情況下,自己實(shí)現(xiàn)一個(gè)promise?

JouyPub / 680人閱讀

摘要:上網(wǎng)查了一下好像是標(biāo)準(zhǔn)第二步開寫構(gòu)造函數(shù)什么都不想,先寫一個(gè)構(gòu)造函數(shù),就叫把。對(duì)構(gòu)造函數(shù)再次做修改。并且可以一個(gè)值。給下一個(gè)繼續(xù)調(diào)用。應(yīng)該是一個(gè)新的。最后的版本總結(jié)后來去看了看別人實(shí)現(xiàn)的方法。

我能不能在不看別人怎么實(shí)現(xiàn)promise的情況下,自己實(shí)現(xiàn)一個(gè)promise?
都8102年為什么還要寫promise實(shí)現(xiàn)? 

? 年前和年后面試了幾家公司, 雖然都掛了… 但是都談到了一個(gè)面試題,就是promise. 雖然使用promise很簡(jiǎn)單,而且我回答的都沒問題.

? 但是面試官都問到了一個(gè)題目. "如果讓你實(shí)現(xiàn)一個(gè)promise.all方法, 怎么實(shí)現(xiàn) ? " 臨時(shí)想了一個(gè)每個(gè)promise.then里用計(jì)數(shù)器+1, 在判斷計(jì)數(shù)器是否等于參數(shù)Array[promise]的 length 來判斷promise是否都完成的實(shí)現(xiàn)思路, 也不知道算不算是對(duì)的.

? 然后就回來想自己能不能在不看任何人的代碼的情況下, 實(shí)現(xiàn)一個(gè)promise。

第一步: 先稍微分析一下原生的Promise Promise 使用方式

var a = new Promise(function( resolve, reject ){})

new一個(gè)Promise實(shí)例,傳入一個(gè)函數(shù),里面有兩個(gè)參數(shù)。

resolve:成功時(shí)調(diào)用,并將成功后的數(shù)據(jù)傳進(jìn)then方法里。

reject:失敗的時(shí)候調(diào)用,并將失敗的數(shù)據(jù)傳進(jìn)catch方法里。

Promise的原型方法

很簡(jiǎn)單,只有我們常見的then catch還有finally方法。不過finally方法應(yīng)該不屬于ES6標(biāo)準(zhǔn)的,所以先忽略。(上網(wǎng)查了一下好像是ES2018標(biāo)準(zhǔn))

第二步:開寫 2.1:構(gòu)造函數(shù)

什么都不想,先寫一個(gè)構(gòu)造函數(shù),就叫 Future 把。

因?yàn)镻romise有兩種狀態(tài),所以我給他加一個(gè) status。

function Future(func){
  this.status = null;
}
2.2:增加resolve和reject

? 接著需要執(zhí)行傳入的函數(shù),并傳給他一個(gè)resolvereject方法。經(jīng)常用Promise的同學(xué)應(yīng)該知道 Promise.resolvePromise.reject。

? 但是沒在原型里找到這兩個(gè)方法,所以我就直接在Future上加這兩個(gè)方法。

// 只要執(zhí)行了resolve或者reject肯定要改變status, 所以對(duì)實(shí)例的status做更新
Future.resolve = function (data) {
  this.status = "resolve"
  this.data = data
}

Future.reject = function (data) {
  this.status = "reject"
  this.data = data
}

這兩個(gè)這里的data要在then里用,所以還是得緩存起來,然后將這兩個(gè)方法傳進(jìn)func里,這里對(duì)構(gòu)造函數(shù)再做改動(dòng)

function Future(func){
  this.status = null;
  this.data = null;
  
  func(Future.resolve, Future.resolve)
}

? 但是這里有一個(gè)問題,resolve執(zhí)行的時(shí)候,this并不是指向當(dāng)前的promise實(shí)例的,這時(shí)我就想到了bind方法。所以必須在初始化的時(shí)候把resolve和reject的作用域給綁定好。對(duì)構(gòu)造函數(shù)再次做修改。( 還要加上setTimeout , 加入even loop,這個(gè)是后加的)

function Future(func){
  if(typeOf func !== "function") throw new Errow("Future 的參數(shù)必須為函數(shù)");
  
  var _this = this;
  this.status = null;
  this.data = null;
  setTimeout(function () {
    func(Future.resolve.bind(_this), Future.resolve.bind(_this))
  })
}
2.3:實(shí)現(xiàn)then和catch
回顧一下then的使用方式:傳入一個(gè)函數(shù),在promise執(zhí)行resolve后,才會(huì)調(diào)用,并且函數(shù)的參數(shù)就是調(diào)用resolve的時(shí)候傳入的值。并且可以return一個(gè)值。給下一個(gè)then繼續(xù)調(diào)用。

? 所以then函數(shù)應(yīng)該很簡(jiǎn)單,直接緩存這個(gè)函數(shù),resolve的時(shí)候再拿出來調(diào)用即可。而關(guān)于鏈?zhǔn)秸{(diào)用,一開始想到的就是return this

? 所以一開始我先是這么寫的

function Future(func){
      //再加一個(gè)函數(shù)隊(duì)列數(shù)組和一個(gè)錯(cuò)誤狀態(tài)的執(zhí)行函數(shù)
      this.queue = [];
      this.failCb = null;
     ...其余代碼省略
}
Future.prototype.then = function (callback) {
      if(typeof callback !== "function") throw new Errow("then必須傳入函數(shù)");
  
    if(this.status === "resolve"){
        this.data = callback(this.data);
    }else if(this.status === null){
        this.queue.push(callback);
   }

   return this;
}

Future.prototype.catch = function (callback) {
      if(typeof callback !== "function") throw new Errow("catch必須傳入函數(shù)");
  
    if (this.status === "reject") {
        this.data = callback(this.data);
    }else if(this.status === null){
        this.failCb = callback;
    }
  
    return this;
}
2.4:實(shí)現(xiàn)resolve和reject

? 其他的都好了,接著就是在resolve里去執(zhí)行隊(duì)列里的函數(shù)。reject里執(zhí)行錯(cuò)誤函數(shù)。

Future.resolve = function (data) {
    var context = this;
    context.status = "resolve";
    context.data = data;
  
      //先把第一個(gè)函數(shù)拿出來
    var func = context.queue.shift();
    if(func){
        try{
            var d = func(data);
              //函數(shù)可以返回一個(gè)值,也可以返回一個(gè)promise
            if(d instanceof Future){
                d = d.data;
            }
              //遞歸的方式再執(zhí)行下一個(gè),這里再用call去改變this的指向
            Future.resolve.call(context, d);
        }catch(err){
              //捕捉報(bào)錯(cuò),執(zhí)行catch
            Future.reject.call(context, err);
        }
    }
}

Future.reject = function (data) {
    this.status = "reject";
    this.data = data;
    if(this.failCb){
        this.failCb(data)
    }else{
        throw new Error("promise catch")
    }
}

以上。

? 到這里呢,就是那時(shí)臨時(shí)想臨時(shí)做的第一版。

后記

? 當(dāng)然,后面又大改了一些東西。最主要的是then函數(shù)不應(yīng)該返回this。應(yīng)該是一個(gè)新的promise。如果按照現(xiàn)在這么做,經(jīng)過多個(gè)then之后,初始的data就變成了最后一個(gè)值了。我們希望的是要保留最初初始化的時(shí)候的那個(gè)值。

//比如
var a = new Future(function(resolve, reject){
    setTimeout(function(){
        console.log("success")
        resolve(true)
    }, 1000)
})

a.then(function(res){
    console.log(res);
    return "啦拉拉"
})

setTimeout(function(){
    a.then(function(res){
          //這里就會(huì)輸出 "啦拉拉"。其實(shí)期望的是輸出 true
        console.log("settimeout: ", res)
    })
},2000)

? 后來為了解決這個(gè),突然陷入了牛角尖。。。花了一天才做完。水平有限,只能做到這樣了,最后附上完整代碼吧。

最后的版本

總結(jié)

? 后來去看了看別人實(shí)現(xiàn)的方法。大體思路應(yīng)該也是差不多的。其實(shí)就做個(gè)記錄總結(jié),方便以后面試用。嘻嘻(^__^)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94033.html

相關(guān)文章

  • 讓你從頭到尾把promise明明白白

    摘要:它的作用是為實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)。里面有兩個(gè)回調(diào)函數(shù),前者返回的回調(diào)函數(shù),后者是可選值。可以看成是的別名專門用來指定錯(cuò)誤發(fā)生時(shí)的回調(diào)函數(shù)。 最近一直私下在看Android項(xiàng)目,前端這一塊沒怎么仔細(xì)研究。昨天在寫重構(gòu)公司前端項(xiàng)目的時(shí)候,我發(fā)現(xiàn)一旦有異步的任務(wù),腦海里面條件反射一般的出現(xiàn)promise的字樣。重構(gòu)的多了 心就就在納悶:既然promise這么好用,我能不能自己手寫一個(gè)pro...

    silenceboy 評(píng)論0 收藏0
  • babel入門

    摘要:為了方便,團(tuán)隊(duì)將一些集合在一起,并稱之為。先看一下直觀體驗(yàn)源代碼配置編譯后的代碼通過對(duì)比可以看出,第二種方案直接從引入,避免自己定義,從而減少代碼的體積。 Babel Babel 是一個(gè) JavaScript 編譯器,它可以將ES6+語(yǔ)法編譯為瀏覽器支持的ES5語(yǔ)法。要學(xué)好babel必須先理解相關(guān)的概念,但是你剛起步就去扣這些細(xì)節(jié)的話,很可能因?yàn)閎abel一些復(fù)雜而模糊的概念打擊你的信...

    pkwenda 評(píng)論0 收藏0
  • ES6常用知識(shí)學(xué)習(xí)札記

    摘要:在年正式發(fā)布了,簡(jiǎn)稱,又稱為。再次簡(jiǎn)寫循環(huán)迭代數(shù)組每個(gè)元素都執(zhí)行一次回調(diào)函數(shù)。方法用于調(diào)用數(shù)組的每個(gè)元素,并將元素傳遞給回調(diào)函數(shù)。注意對(duì)于空數(shù)組是不會(huì)執(zhí)行回調(diào)函數(shù)的。 轉(zhuǎn)載請(qǐng)注明出處 原文連接 http://blog.huanghanlian.com/article/5c7aa6c7bf3acc0864870f9d es6 是什么 首先弄明白ECMA和js的關(guān)系。ECMA是標(biāo)準(zhǔn),Jav...

    googollee 評(píng)論0 收藏0
  • ES6常用知識(shí)學(xué)習(xí)札記

    摘要:在年正式發(fā)布了,簡(jiǎn)稱,又稱為。再次簡(jiǎn)寫循環(huán)迭代數(shù)組每個(gè)元素都執(zhí)行一次回調(diào)函數(shù)。方法用于調(diào)用數(shù)組的每個(gè)元素,并將元素傳遞給回調(diào)函數(shù)。注意對(duì)于空數(shù)組是不會(huì)執(zhí)行回調(diào)函數(shù)的。 轉(zhuǎn)載請(qǐng)注明出處 原文連接 http://blog.huanghanlian.com/article/5c7aa6c7bf3acc0864870f9d es6 是什么 首先弄明白ECMA和js的關(guān)系。ECMA是標(biāo)準(zhǔn),Jav...

    tracymac7 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<