国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

JouyPub / 676人閱讀

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

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

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

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

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

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

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

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

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

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

Promise的原型方法

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

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

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

因為Promise有兩種狀態(tài),所以我給他加一個 status

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

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

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

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

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

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

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

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

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:實現(xiàn)then和catch
回顧一下then的使用方式:傳入一個函數(shù),在promise執(zhí)行resolve后,才會調用,并且函數(shù)的參數(shù)就是調用resolve的時候傳入的值。并且可以return一個值。給下一個then繼續(xù)調用。

? 所以then函數(shù)應該很簡單,直接緩存這個函數(shù),resolve的時候再拿出來調用即可。而關于鏈式調用,一開始想到的就是return this

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

function Future(func){
      //再加一個函數(shù)隊列數(shù)組和一個錯誤狀態(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:實現(xiàn)resolve和reject

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

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

以上。

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

后記

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

//比如
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){
          //這里就會輸出 "啦拉拉"。其實期望的是輸出 true
        console.log("settimeout: ", res)
    })
},2000)

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

最后的版本

總結

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

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

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94033.html

相關文章

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

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

    silenceboy 評論0 收藏0
  • babel入門

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

    pkwenda 評論0 收藏0
  • ES6常用知識學習札記

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

    googollee 評論0 收藏0
  • ES6常用知識學習札記

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

    tracymac7 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<