JavaScript中Promises/A+規范的實現

jopen 8年前發布 | 10K 次閱讀 JavaScript開發 JavaScript

Promises是一種異步編程模型,通過一組API來規范化異步操作,這樣也能夠讓異步操作的流程控制更加容易。

下面的代碼是假設執行一個異步隊列,每一項都會使用上一項返回的數據:

function nest(url, params, fn) {
    $.getJSON(url, params, function(data) {
        console.log(data);
        fn.call(this);
    });
}
nest('promise.php', {a:1}, function(data1) {
    nest('promise.php', {b:2}, function(data2) {
        nest('promise.php', {c:3}, function(data3) {
            console.log('同步完成');
        });
    });
});

這是一個回調金字塔,當異步的任務很多的時候,需要維護大量的callback。這嵌套的自己眼睛都看不清了吧。

Promise/A+規范就是為了解決上面的問題,可以用類似下面的代碼來改進,“nest”也會做些修改:

promise.then(nest('promise.php', {a:1}))
    .then(nest('promise.php', {b:2}))
    .then(nest('promise.php', {c:3}));

下圖是改進的圖片示例,我在畫圖的時候也感覺到,左邊的比較難畫,右邊的很好畫。

接下來會圍繞改進金字塔,實現規范展開。

一、Promises/A+規范說明

Promises/A+規范 如下:

1)一個promise可能有三種狀態:等待(pending)、已完成(fulfilled)、已拒絕(rejected)

2)一個promise的狀態只可能從“等待”轉到“完成”態或者“拒絕”態,不能逆向轉換,同時“完成”態和“拒絕”態不能相互轉換

3)promise必須實現then方法,而且then必須返回一個promise

4)同一個promise的then可以調用多次,并且回調的執行順序跟它們被定義時的順序一致

5)then方法接受兩個參數,第一個參數是成功時的回調,在promise由“等待”態轉換到“完成”態時調用

6)另一個是失敗時的回調,在promise由“等待”態轉換到“拒絕”態時調用。

7)then可以接受另一個promise傳入,也接受一個“類then”的對象或方法,即thenable對象。

接下來先實現一個簡易的,只有完成狀態,沒有拒絕和等待狀態。

二、簡單實現

Promise對象的實現:

function Promise(fn) {
  this._status = 'pending';
  this._resolves = []; //隊列
  this._fn = fn;
  return this;
}
Promise.prototype = {
  then: function(resolve) {
    var next = this._next || (this._next = new Promise()); //下一個promise對象
    this._resolves.push(resolve); //設置隊列
    return next;
  },
  resolved: function(value) { //改變狀態
    this._status = 'fulfilled';
    this._result = (this._fn && this._fn(value)) || value;
    while (fn = this._resolves.shift()) { //循環調用隊列
      this._fire(this._next, fn);
    }
  },
  _fire: function(nextPromise, nextFn) {
    var nextResult = nextFn(this._result);
    if (nextResult instanceof Promise) { //判斷回調是否是Promise對象
      //只有當nextResult的狀態為fulfilled,下一個promise才可以執行
      nextResult.then(function(value) {
        nextPromise.resolved(value);
      });
    } else {
      nextPromise.resolved(nextResult);
    }
  }
};

演示用的函數:

function nest2(url, params) {
  return function(pre) {
    var promise = new Promise();
    $.getJSON(url, params, function(data) {
      promise.resolved(data);
    });
    return promise;
  };
}

function begin(value) {
  return value + '!';
}

初始化代碼:

var promise = new Promise(begin);
promise.then(nest2('promise.php', {a: 1}))
  .then(nest2('promise.php', {b: 2}));
promise.resolved('開始');

也可以另外一種方式調用,這樣的話內部的_resloves隊列中會有多個值

var promise = new Promise(begin);
promise.then(nest2('promise.php', {a: 1}))
promise.then(nest2('promise.php', {b: 2}));
promise.resolved('開始');

demo下載:

http://download.csdn.net/detail/loneleaf1/9391315

參考資料:

http://www.alloyteam.com/2014/05/javascript-promise-mode/ JavaScript Promise啟示錄

http://www.cnblogs.com/fsjohnhuang/p/4135149.html JS魔法堂:剖析源碼理解Promises/A規范

http://www.cnblogs.com/aaronjs/archive/2012/11/17/2774440.html 使用Promises/A

http://rapheal.sinaapp.com/2013/01/26/jquery-src-deferred/ $.Deferred

http://www.ituring.com.cn/article/66566 Promises/A+規范

來自: http://www.cnblogs.com/strick/p/5092092.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!