promise基本實現思路

BFC發表於2018-06-12

promise是用來解決瘋狂地獄式回撥函式的問題,多種巢狀回撥函式的方式不利於程式碼的維護,於是是否可以讓回撥函式不用巢狀,按照同步的方式來寫

先看一段promise函式的簡單程式碼的應用:

new Promise(function(resolve, reject) {
    console.log('init');
    resolve('then1');
}).then(function(val) {
    console.log(val);
    return "then2";
}).then(function(val) {
    console.log(val);
})

結果:
init
then1
then2
複製程式碼

分析:

1.根據promise的建構函式來看,只有呼叫resolve方法後,才會執行then後面的函式

2.then方法可以鏈式呼叫,上一層的then函式返回值可以傳給下一層的函式then的引數

猜想:

當呼叫resolve方法後,then後面的函式是依次執行的,then函式可能是會將傳入的函式引數儲存到內部陣列去,但是為了確保在resolve之後,then所有的函式引數都已經儲存起來,resolve方法執行順序可能是非同步的;可能還會存在一個儲存then函式之間傳遞的內部引數值。

下面寫個簡單例項來探究:

function MPromise(fn) {
  this.thenCb = [];
  this.state = null;
  this.value = null;

  fn(this.resolve, this.reject, this);
}

MPromise.prototype.then = function(onResolve, onReject) {
  this.thenCb.push(onResolve);
  return this;
}

MPromise.prototype.resolve = function(_value, self) {
  setTimeout(() => {
    self.value = _value;
    for (var i = 0; i < self.thenCb.length; i++) {
      self.value = self.thenCb[i](self.value);
    }
  }, 0);
}

var p = new MPromise((resolve, reject, self) => {
  console.log('init');
  resolve('then1', self);
}).then(val => {
  console.log(val);
  return 'then2'
}).then(val => {
  console.log(val);
});

結果:
init
then1
then2
複製程式碼

似乎這個已經可以實現當前的功能了。細究一下resolve方法必須是非同步的,否則還沒等到將then方法的函式引數儲存起來就已經呼叫了,那麼如何實現非同步呢?

js提供四種實現非同步的定時器機制

setTimeout;setImmediate;Process.nextTick

setImmediate和Process.nextTick的區別

A(); B(); C(); promise基本實現思路------------------------------------------------------------------------A(); process.nextTick(B); C(); promise基本實現思路------------------------------------------------------------------------A(); setImmediate(B); C(); promise基本實現思路

process.nextTick:在本輪迴圈結束後立刻執行,相當於微任務

setImmediate:在次輪迴圈開始最後才執行,相當於巨集任務

參考:事件迴圈佇列

所以一般在低版本ie8瀏覽器下,選擇使用setTimeout來實現非同步。

言歸正傳:知道如何實現非同步之後,如果then函式返回是一個新的promise,該如何區分執行

promise原始碼中

// States:
//
// 0 - pending
// 1 - fulfilled with _value
// 2 - rejected with _value
// 3 - adopted the state of another promise, _value
//
// once the state is no longer pending (0) it is immutable
複製程式碼

promise狀態一旦改變就不可以更改,並且只允許從0 -> 1/2/3,界定每個promise的狀態值來解決

還有reject, catch, promise.all, promise.race如何實現,下次更新。

相關文章