Promise執行順序(上)

代碼執行順序

const first = () =>
    new Promise((resolve, reject) => {
        resolve(2);
        console.log(3);
        let p = new Promise((resolve, reject) => {
            console.log(7);
            resolve(1);
        })
        p.then(arg => {
            console.log(arg);
        })
    })
first().then(arg => {
    console.log(arg);
})
console.log(4);
複製代碼

Promise構造函數

function Promise(resolver) {
  if (typeof resolver !== 'function') {
    throw new TypeError('resolver must be a function');
  }
  this.state = PENDING;
  this.queue = [];
  this.outcome = void 0;
  if (resolver !== INTERNAL) {
    safelyResolveThenable(this, resolver);
  }
}
複製代碼
  1. 執行first()
  2. new Promise進入構造函數
  3. 執行safelyResolveThenable
function safelyResolveThenable(self, thenable) {
  // Either fulfill, reject or reject with error
  var called = false;
  function onError(value) {
    if (called) {
      return;
    }
    called = true;
    handlers.reject(self, value);
  }

  function onSuccess(value) {
    if (called) {
      return;
    }
    called = true;
    handlers.resolve(self, value);
  }

  function tryToUnwrap() {
    thenable(onSuccess, onError);
  }

  var result = tryCatch(tryToUnwrap);
  if (result.status === 'error') {
    onError(result.value);
  }
}
複製代碼
  1. 實際執行tryToUnwrapthenable(onSuccess, onError);
  2. thenable = 當初Promise傳入的如下代碼
(resolve, reject) => {
    resolve(2);
    console.log(3);
    let p = new Promise((resolve, reject) => {
        console.log(7);
        resolve(1);
    })
    p.then(arg => {
        console.log(arg);
    })
}
複製代碼
  1. 執行resolve(2)
  2. 即執行
function onSuccess(value) {
    if (called) {
      return;
    }
    called = true;
    // value = 2
    handlers.resolve(self, value);
}
複製代碼
  1. handlers.resolve
handlers.resolve = function (self, value) {
  // 每次執行都過tryCatch,這也是爲何能最後Catch到的緣由
  var result = tryCatch(getThen, value);
  if (result.status === 'error') {
    return handlers.reject(self, result.value);
  }
  var thenable = result.value;
  // thenable = undefined
  if (thenable) {
    safelyResolveThenable(self, thenable);
  } else {
    // 進入這裏
    self.state = FULFILLED;
    // outcome記錄2
    self.outcome = value;
    var i = -1;
    // self.queue = []
    var len = self.queue.length;
    // 沒有執行的
    while (++i < len) {
      self.queue[i].callFulfilled(value);
    }
  }
  return self;
};
複製代碼
  1. 同樣的執行順序
  2. 打印7,執行resolve(1);
  3. getThen(這步返回undefined),與本題無關
function getThen(obj) {
  // Make sure we only access the accessor once as required by the spec
  var then = obj && obj.then;
  // 判斷傳入參數是否是Promise
  if (obj && (typeof obj === 'object' || typeof obj === 'function') && typeof then === 'function') {
    return function appyThen() {
      then.apply(obj, arguments);
    };
  }
}
複製代碼
  1. then
Promise.prototype.then = function (onFulfilled, onRejected) {
  if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
    typeof onRejected !== 'function' && this.state === REJECTED) {
    return this;
  }
  // 新生成Promise
  var promise = new this.constructor(INTERNAL);
  // this.state = "FULFILLED"
  if (this.state !== PENDING) {
    // 進入這裏resolver = onFulfilled
    var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
    // this.outcome = 1, promise = 新構造的
    unwrap(promise, resolver, this.outcome);
  } else {
    this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
  }

  return promise;
};
複製代碼
  1. unwrap
function unwrap(promise, func, value) {
  // task = immediate裏面的funciton
  immediate(function () {
    var returnValue;
    try {
      returnValue = func(value);
    } catch (e) {
      return handlers.reject(promise, e);
    }
    if (returnValue === promise) {
      handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
    } else {
      handlers.resolve(promise, returnValue);
    }
  });
}
複製代碼

immediate.js

var Mutation = global.MutationObserver || global.WebKitMutationObserver;
var called = 0;
var observer = new Mutation(nextTick);
var element = global.document.createTextNode('');
observer.observe(element, {
    characterData: true  // 設置true,表示觀察目標數據的改變
});
// 改變element.data數據變化
scheduleDrain = function () {
    // (called = ++called % 2) 對一個整數called對2取模,獲得0或者1
    // element.data數據變化一次,執行一次nextTick回調
    element.data = (called = ++called % 2);
};
// 當queue = [], draining = undefined
function immediate(task) {
    if (queue.push(task) === 1 && !draining) {
        scheduleDrain(); // 執行scheduleDrain
    }
}
var draining;
var queue = [];

function nextTick() {
    draining = true;
    var i, oldQueue;
    // 這段代碼的意思
    // 在nextTick執行過程當中,queue隊列裏面添加進來的任務
    // 所有執行完畢
    var len = queue.length;
    while (len) {
        oldQueue = queue;
        queue = [];
        i = -1;
        while (++i < len) {
            // i 從0開始執行,先進先執行,知足隊列的執行機制,執行完成後
            oldQueue[i]();
        }
        // 判斷queue是否有新任務加入。改變了len
        // 若是len改變,繼續上面的while不退出
        len = queue.length;
    }
    draining = false;
}
複製代碼
  1. immediate
// 當queue = [], draining = undefined
function immediate(task) {
    if (queue.push(task) === 1 && !draining) {
        scheduleDrain(); // 執行scheduleDrain
    }
}
複製代碼
  1. scheduleDrain執行
  2. 執行first().then
  3. 再次執行14步驟,可是隻push,不執行裏面的scheduleDrain
  4. 而後打印console.log(4);
  5. 如今執行nextTick回調
  6. 按照先進先出,打印1,2
相關文章
相關標籤/搜索