理解jQuery中的Promise

首先回顧一下jQuery的deferred對象:
jQuery的deferred對象

關於Promise的進化史

在jQuery1.4中,還沒有promise這個概念,寫一個ajax,就得寫回調函數,就像這樣:

$.get('/myData', {
    success: onSuccess,
    failure: onFailure,
    always: onAlways
})

到了jQuery1.5+之後,有了promise,就可以給ajax 的get返回的就是一個promise對象(我這樣理解不知道對不對)
然後代碼的形式就變成了這樣:

var promise = $.get('/myData');
promise.done(onSuccess);
promise.fail(onFailure);
promise.always(onAlways);

這樣的好處是Promise對象和EventEmitter對象一樣,可以向同一事件綁定任意多的處理器。

promise就是deferred

或者說是用deferred就可以生成一個promise對象

var prompt = new $.Deferred();
$('#playGame').focus().on('keypress', function(e) {
    var Y = 121,
        N = 110;
    if (e.keyCode === Y) {
        prompt.resolve();
    } else if (e.keyCode === N) {
        prompt.reject();
    } else {
        return false; // they must choose!
    }
});
prompt.done(function() {
    console.log('Starting game...');
});
prompt.fail(function() {
    console.log('No game today.');
});
prompt.always(function() {
    console.log('A choice was made');
});

輸入y就會打印
這裏寫圖片描述
輸入n就會打印
這裏寫圖片描述
即,每次調用promtDeferred對象,都會先運行一下always(),再運行done或者fail(調用promt.resolve()就是done,reject就是fail)
同時測試結果顯示錶明,調用了一次之後就不管用了。也就是說Promise對象只能執行或拒絕一次,之後就失效了。期間Promise對象會一直保持掛起狀態。
這裏我們可以調用promt.state()方法,確實是“pending”
這裏我打印一下promt對象的屬性和方法,就可以看到promise的方法有always,done,fail,notify…..
這裏寫圖片描述

生成一個純promise對象

上面的圖,我們可以看到promt有一個promise()方法,沒錯,就是調用這個方法來生成純promise對象。
這裏寫圖片描述
promise對象和Deferred對象的區別是,沒有resolve和reject方法。promise的promise也是指向自己。

因此可以考慮這是一個封裝:每個deferred對象都含有一個promise對象,每個promise對象都代表着一個deferred對象。有了deferred對象,就可以控制其狀態,有了promise對象就可以讀取其狀態。

jQuery中的Promise對象

還是參見上面的圖,很多方法都沒有介紹
首先,說明的是在jQuery中,不僅只有Ajax函數(.ajax,.get, .post)可以返回Promise對象,動畫函數也可以返回Promise對象。

notify和progress

Promise對象接受3種回調方式:done、fail和progress。
- 執行Promise對象時,運行的是done回調;
- 拒絕Promise對象時,運行的是fail回調;
- 對於掛起狀態的Deferred對象調用notify,運行的是progress回調;

when

when相當於Promise執行情況的邏輯與運算符(AND)。一旦給定的所有Promise均已執行,就立即執行when產生的Promise對象;
或者,一旦給定的任意一個Promise被拒絕,就立即拒絕when產生的Promise。

pipe

pipe是jquery1.6+提供的方法。
pipe是promise上的方法,pipe對象也是promise對象。
這裏寫圖片描述
初始Promise對象的行爲一直級聯到管道末尾的promise對象。

Promise對象的使用

用Promise對象代替回調函數

deferreCallback = function(deferred) {
    return function(err) {
        deferred.reject(err)
    } else {
        deferred.resolve(Array.prototype.slice.call(arguments, 1));
    }
}
var fileReading = new $.Deferred();
fs.readFile(filename, 'utf8', deferreCallback(fileReading));

文件讀取是一個耗時的工作,我們將Priomise對象代替回調函數,當文件讀取成功就執行deferred.resolve,失敗就執行deferred.reject。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章