Promise 源碼解析—— .then 處理小細(xì)節(jié)

今天看到一段callback代碼

var dataCache = null;

function getAjaxData(callback){
  if ( dataCache ) {
    callback && callback(dataCache);
  } else {
    $.ajax({
     .....
    })
   .done( (res) => {
       dataCache = res;
       callback && callback(res);
   })
  }
}

上面是一個callback 寫的ajax 調(diào)用。 設(shè)置了一個緩存, 在重復(fù)調(diào)用函數(shù)的時候會取緩存。

這時候調(diào)用這個函數(shù)會有一個問題。

getAjaxData( () => {
  console.log(2);
})
console.log(1);

上面的代碼我們會有 先輸出1 后輸出 2 的 預(yù)期。
但實(shí)際上在第二次執(zhí)行該方法會命中緩存,然后先輸出 2 后輸出 1。 于是導(dǎo)致了BUG。

把callback代碼優(yōu)化為 promise 方式。

var dataCache = null;

function getAjaxData(){
  return new Promise( (resolve, rej) => {

  if ( dataCache ) {
    resolve();
  } else {
    $.ajax({
     .....
    })
   .done( () => {
       resolve();
   })
  }

  })
  
}

這個時候就不管調(diào)用多少次都是異步了 OK, 背景介紹完畢。

那我們進(jìn)入正題,來看看Promise是如何實(shí)現(xiàn)的吧。

var asap = require('asap/raw');
...
...
Promise.prototype.then = function(onFulfilled, onRejected) {
  if (this.constructor !== Promise) {
    return safeThen(this, onFulfilled, onRejected);
  }
  var res = new Promise(noop);
  handle(this, new Handler(onFulfilled, onRejected, res));
  return res;
};

function handle(self, deferred) {

  while (self._state === 3) {
    self = self._value;
  }
  if (Promise._onHandle) {
    Promise._onHandle(self);
  }
  if (self._state === 0) {
    if (self._deferredState === 0) {
      self._deferredState = 1;
      self._deferreds = deferred;
      return;
    }
    if (self._deferredState === 1) {
      self._deferredState = 2;
      self._deferreds = [self._deferreds, deferred];
      return;
    }
    self._deferreds.push(deferred);
    return;
  }
  handleResolved(self, deferred);
}

function handleResolved(self, deferred) {
  asap(function() {
    var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
    if (cb === null) {
      if (self._state === 1) {
        resolve(deferred.promise, self._value);
      } else {
        reject(deferred.promise, self._value);
      }
      return;
    }
    var ret = tryCallOne(cb, self._value);
    if (ret === IS_ERROR) {
      reject(deferred.promise, LAST_ERROR);
    } else {
      resolve(deferred.promise, ret);
    }
  });
}

全局搜了 setTimeout 發(fā)現(xiàn)沒有。 那怎么做到強(qiáng)行異步的呢, 唯一可能的地方就是這里用到的 asap 這個庫了。
讓我們看看

asap.js

var rawAsap = require("./raw");
var freeTasks = [];

/**
 * Calls a task as soon as possible after returning, in its own event, with
 * priority over IO events. An exception thrown in a task can be handled by
 * `process.on("uncaughtException") or `domain.on("error")`, but will otherwise
 * crash the process. If the error is handled, all subsequent tasks will
 * resume.
 *
 * @param {{call}} task A callable object, typically a function that takes no
 * arguments.
 */

Calls a task as soon as possible after returning。

we get it!

這個庫的實(shí)現(xiàn)源碼如下, 值得一看
https://github.com/kriskowal/asap/blob/master/browser-raw.js

setTimeout(function(){
  console.log(2);
}, 0);
var observer = new MutationObserver(function(){
  console.log(1);
});
var node = document.createTextNode("");
observer.observe(node, {characterData: true});
node.data = 1;

console.log(3);

上面代碼的輸出是什么呢?^?_?^

歡迎吐槽筆者自己寫的 proimse。
https://github.com/KMBaby-zyl/tiny-co/blob/master/promise/promise.js

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文: https://github.com/ecomfe/spec/blob/master/javascript...
    zock閱讀 3,475評論 2 36
  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 11,115評論 26 95
  • 你不知道JS:異步 第三章:Promises 在第二章,我們指出了采用回調(diào)來表達(dá)異步和管理并發(fā)時的兩種主要不足:缺...
    purple_force閱讀 2,226評論 0 4
  • 00、前言Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)...
    夜幕小草閱讀 2,217評論 0 12
  • 似乎已經(jīng)過了很久 偷偷暗戀你的我 怕被你發(fā)現(xiàn)而焦慮 獨(dú)自煩惱要不要跟你說話 你知道我的心意嗎 你故意裝傻的嗎 適度...
    心若堅(jiān)冰閱讀 432評論 0 1

友情鏈接更多精彩內(nèi)容