jQuery中Deferred的实现原理


Deferred提供了一种用非阻塞的串行逻辑方式编写异步执行代码。


defer的用法:

function doJob() {
    var defer = $.Deferred();
    var image = new Image();
    var url = "http://hiphotos.baidu.com/j_fo/pic/item/5fd4af345982b2b7e633367931adcbef77099b6b.jpg";
    image.onload = function() {
        alert("success");
        defer.resolve( url );
    };
    image.onerror = function() {
        alert("error");
        defer.reject( url );
    };
    image.src = url;
    return defer.promise();
}
doJob().done(function(){
    alert("done");
});

更多例子:使用jQuery Deferred 和 Promise 创建响应式应用程序



实现原理参考如下实现代码:

function Deferred() {
    return new Deferred.prototype.init();
}
Deferred.prototype.init = function() {
    this.state = 0;
    this.doneQueue = [];
    this.failQueue = [];
    return this;
}
Deferred.prototype.init.prototype = Deferred.prototype;
Deferred.prototype.promise = function(){
    return this;
}
Deferred.prototype.done = function(cbDone){
    this.doneQueue.push(cbDone);
    if (this.state != 0)
        this._finish();
    return this;
}
Deferred.prototype.fail = function(cbFail){
    this.failQueue.push(cbFail);
    if (this.state != 0)
        this._finish();
    return this;
}
Deferred.prototype.resolve = function(){
    this.state = 1;
    this.args = arguments;
    this._finish();
}
Deferred.prototype.reject = function(){
    this.state = 2;
    this.args = arguments;
    this._finish();
}
Deferred.prototype._finish = function(){
    var queue = [];
    if (this.state == 1)
        queue = this.doneQueue;
    else if (state == 2)
        queue = this.failQueue;
    for (var i = 0; i < queue.length; i++) {
        var cb = queue[i];
        cb.apply(this, this.args);
    }
}