天天看點

JavaScript簡單實作Promise/A+規範Promise/A+規範是什麼簡單的實作代碼

Promise/A+規範是什麼

Promise表示一個異步操作的最終結果。與Promise最主要的互動方法是通過将函數傳入它的then方法進而擷取得Promise最終的值或Promise最終最拒絕(reject)的原因。具體詳細的講解請移步:

- wikipedia上的介紹

-官方介紹網址

簡單的實作代碼

'use strict';

Promise = () => {};

var isPromise = (value) => {
    return value instanceof Promise;
};

var defer = () => {
    var pending = [], value;
    var promise = new Promise();
    promise.then = (callback) => {
        if (pending) {
            pending.push(callback);
        } else {
            callback(value);
        }
    };
    return {
        resolve: function (_value) {
            if (pending) {
                value = _value;
                for (var i = , ii = pending.length; i < ii; i++) {
                    var callback = pending[i];
                    callback(value);
                }
                pending = undefined;
            }
        },
        promise: promise
    };
};
           

github上找到的一篇更加詳細的實作:github位址

更加詳細的代碼實作(對應将中文翻譯成為了中文):

(function() {
  'use strict';

  // 用于異步執行 onFulfilled/onRejected
  // `setImmediate` or `function(fn) { setTimeout(fn,) }` in browser
  // `process.nextTick` in node
  var asyncCall = process.nextTick;

  //
  // Promise解析過程 是以一個promise和一個值做為參數的抽象過程,可表示為[[Resolve]](promise, x)
  function resolve(promise, x) {
    //.1
    // 如果promise 和 x 指向相同的值, 使用 TypeError做為原因将promise拒絕
    if (promise === x) {
      return promise.reject(new TypeError('The promise and its value refer to the same object'));
    }
    //.3
    // 如果x是一個對象或一個函數
    if (x && (typeof x === 'function' || typeof x === 'object')) {
      //.3.3
      // 如果 resolvePromise 和 rejectPromise 都被調用了,或者被調用了多次,則隻第一次有效,後面的忽略。
      // 我們用 called 作為辨別防止被多次調用
      var called = false,then;
      try { //.3.1 // 将 then 賦為 x.then then = x.then; if (typeof then === 'function') { //.3.3 // 如果 then 是一個函數,以x為this調用then函數,且第一個參數是resolvePromise,第二個參數是rejectPromise then.call(x, function(y) { //.3.3.1 // 當 resolvePromise 被以y為參數調用,執行 [[Resolve]](promise, y) if (!called) { called = true; resolve(promise, y); } }, function(r) { //.3.3.2 // 當 rejectPromise 被以 r 為參數調用,則以r為原因将promise拒絕。 if (!called) { called = true; promise.reject(r); } }); }else { //.3.4 // 如果 then不是一個函數,則 以x為值fulfill promise promise.fulfill(x); } }catch (e) { //.3.2 // 如果在取x.then值時抛出了異常,則以這個異常做為原因将promise拒絕 if (!called) { called = true; promise.reject(e); } }
    }else {
      //.4
      // 如果 x 不是對象也不是函數,則以x為值 fulfill promise
      promise.fulfill(x);
    }
  }

  function Taxi() {
    // pending, fulfilled, rejected
    var _state =,
      _value,
      _onFulfills = [],
      _onRejects = [];
    this.done = function(onFulfilled, onRejected) {
      if (_state ===) {// 如果還在pending,先把處理函數存起來 _onFulfills.push(onFulfilled); _onRejects.push(onRejected); }else {// 否則,異步執行 asyncCall(function() { if (_state ===) { if (typeof onFulfilled === 'function') { onFulfilled(_value); } }else if (typeof onRejected === 'function') { onRejected(_value); } }); }
    };

    /**
     * 用于this.fulfill和this.reject内部調用的函數
     * @param  {number} state->pending,->fulfill,->reject
     * @param  {dynamic} value result 或 reason
     */
    function _complete(state, value){
      // 隻能 fulfill或reject一次, 後面的忽略
      if (!_state) { _state = state; _value = value; // 根據 state 擷取需要處理的函數數組 // 異步執行 asyncCall(function() { var handlers = state == ? _onFulfills : _onRejects; handlers.forEach(function(fn) { if (typeof fn === 'function') { fn(value); } }); // 執行完之後,解除數組引用 _onFulfills = null; _onRejects = null; }); }
    }
    this.fulfill = function(value) {
      _complete(1, value);
    };
    this.reject = function(value) {
      _complete(2, value);
    };
  }

  Taxi.prototype = {
    constructor: Taxi,
    catch: function(onRejected) {
      this.then(null, onRejected);
    },
    then: function(onFulfilled, onRejected) {
      //.7
      // then 必須傳回一個promise
      // 是以我們new一個,等下用于傳回
      var taxi = new Taxi();

      // this指向目前promise
      //.2
      // 如果onFulfilled是一個函數:
      // 它必須在promise fulfilled後調用, 且promise的value為其第一個參數。
      //.3
      // 如果onRejected是一個函數,
      // 它必須在promise rejected後調用, 且promise的reason為其第一個參數。
      this.done(function(x) { if (typeof onFulfilled === 'function') { try { //.7.1 // 如果onFulfilled 或 onRejected 傳回了值x, // 則執行Promise 解析流程[[Resolve]](promise2, x). resolve(taxi, onFulfilled(x)); }catch (e) { //.7.2 // 如果onFulfilled 或 onRejected抛出了異常e, // 則promise2應當以e為reason被拒絕 taxi.reject(e); } }else { //.7.3 // 如果 onFulfilled 不是一個函數且promise1已經fulfilled, // 則promise2必須以promise1的值fulfilled. taxi.fulfill(x); } }, function(x) { if (typeof onRejected === 'function') { try { //.7.1 // 如果onFulfilled 或 onRejected 傳回了值x, // 則執行Promise 解析流程[[Resolve]](promise2, x). resolve(taxi, onRejected(x)); }catch (e) { //.7.2 // 如果onFulfilled 或 onRejected抛出了異常e, // 則promise2應當以e為reason被拒絕 taxi.reject(e); } }else { //.7.4 // 如果 OnReject 不是一個函數且promise1已經rejected, // 則promise2必須以相同的reason被拒絕. taxi.reject(x); } });
      return taxi;
    }
  };
  module.exports = Taxi;
}());
           

更多的實作版本

bluebird

q – Angularjs的$q對象是q的精簡版

繼續閱讀