jQuery的异步回调对象Deffered分析

  先来思考一个问题:一个需要耗时很长的操作比如setTimeout, ajax请求等,我们需要在延时操作后执行一个函数done。

  比如:

 var wait = function(){
    var tasks = function(){
      alert("执行完毕!");
    };
    setTimeout(tasks,5000);
  };

在wait执行完毕后,再执行done或者fail函数。

怎么做?当然,你可以在tasks函数中执行done() 或者 fail() ,但是不够优雅的实现。如果加入异步队列,添加类似jQuery的方法:$.when(wait()).done(function(){}).fail(function(){})。

怎么做到呢?原理很简单,如代码:

var dtd = $.Deferred(); // 新建一个deferred对象
  var wait = function(dtd){
    var tasks = function(){
      alert("执行完毕!");
      dtd.resolve(); // 改变deferred对象的执行状态
    };
    setTimeout(tasks,5000);
    return dtd;
  };
$.when(wait(dtd))
  .done(function(){ alert("哈哈,成功了!"); })
  .fail(function(){ alert("出错啦!"); });

添加一个变量dfd对象,执行完后,改变dfd的状态,状态改变,同时触发相应的方法。

具体来看看jQuery源码。

jQuery为我们抽象了3中状态:done, fail,progress;改变状态的方法:resolve,reject,notify;对应的状态码:resolved,reject;对应的回调的对象:jQuery.Callbacks("once memory")

来看其映射:

var tuples = [
                // action, add listener, listener list, final state
                [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
                [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
                [ "notify", "progress", jQuery.Callbacks("memory") ]
            ]

deferred对象要依赖于Callbacks对象实现。其解析移步Callbacks篇。

然后为deffered对象添加相应方法。

deferred = {};
// 添加[ resolve | reject | notify ]
deferred[ tuple[0] ] = function() {
    deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
    return this;
};
// 添加[ resolveWith | rejectWith | notifyWith ]
deferred[ tuple[0] + "With" ] = list.fireWith;

// 返回这个对象
return deferred;

//继承promise对象
promise: function( obj ) {
    return obj != null ? jQuery.extend( obj, promise ) : promise;
}

promise.promise( deferred );

为promise对象添加相应方法:

// 添加state, always, then, promise
promise = {
    state: function() {
        return state;
    },
    always: function() {
        deferred.done( arguments ).fail( arguments );
        return this;
    },
    then: function( /* fnDone, fnFail, fnProgress */ ) {
        var fns = arguments;
        return jQuery.Deferred(function( newDefer ) {
            jQuery.each( tuples, function( i, tuple ) {
                var action = tuple[ 0 ],
                    fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
                deferred[ tuple[1] ](function() {
                    var returned = fn && fn.apply( this, arguments );
                    if ( returned && jQuery.isFunction( returned.promise ) ) {
                        returned.promise()
                            .done( newDefer.resolve )
                            .fail( newDefer.reject )
                            .progress( newDefer.notify );
                    } else {
                        newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
                    }
                });
            });
            fns = null;
        }).promise();
    },
    promise: function( obj ) {
        return obj != null ? jQuery.extend( obj, promise ) : promise;
    }
},
// 添加pipe
promise.pipe = promise.then;

// 添加[ done | fail | progress ] = list.add
promise[ tuple[1] ] = list.add;

综上:

deferred的方法:

deferred.resolve() 手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。

deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。

deferred.notify()  手动改变deferred对象的运行状态为"正在进行"

deferred.state() 返回状态

deferred.always()

deferred.then() 有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。

deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。

deferred.done() 指定操作成功时的回调函数

deferred.fail() 指定操作失败时的回调函数

deferred.progress() 指定操作正在进行时的回调函数

deferred.pipe()

$.when() 为多个操作指定回调函数。

promise的方法:

除了以上改变状态的三个方法(resolve, reject, notify)

done, fail, progress方法就是回调对象的add方法;

promise[ tuple[1] ] = list.add;

resolve, reject, notify方法就是回调对象的fire方法;

deferred[ tuple[0] ] = function() {
  deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
  return this;
};

deferred[ tuple[0] + "With" ] = list.fireWith;

其中then方法感觉比较复杂,其实是加了pipe方法的内容, 原来内容非常简单

pipe目前用的不多,意义不大,不详细研究

最后是when方法,其实是维护一个变量remaining,当其所有都完成时候触发回调。

  

  

时间: 2024-11-03 05:37:02

jQuery的异步回调对象Deffered分析的相关文章

jQuery的回调对象Callbacks分析

Callbacks在jQuery中的地位是Deferred的基础,当然,也对外公开其方法. Callbacks对象是统一管理多个函数的利器.其核心是参数options中的几个状态码的任意组合,非常灵活. 先来看看options once: 只触发一次回调 memory: 如果是触发后状态,add后立即触发 unique: 添加相同回到函数,只触发其中一个 stopOnFalse: 回调中遇到return false, 后面都不执行. 首先是: list = [] 我们的工作就是在维护这个list

JQuery的异步回调支持 - Promise、Deferred

1.Deferred对象: 一般在函数内部进行声明,并在运行过程中改变其状态,例如成功或失败,最终返回Promise对象用于状态监听. 主要方法: Deferred.resolve(param...) :执行成功,将会触发Promise对象的done回调方法.Deferred.reject(param...) :执行失败,将会触发Promise对象的fail回调方法.Deferred.notify(param...) :正在执行,将会触发Promise对象的progress回调方法.Deferr

jquery源码分析(四)——回调对象 Callbacks

借用百度百科来说明下回调函数: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. jQuery回调对象实现恰好利用了设计模式中的观察者模式思想,观察者模式 (pub/sub) 的背后,总的想法是在应用程序中增强松耦合性.并非是在其它对象的方法上的单个对象调用.一个对象作为特定任务或

jquery.Deferred promise解决异步回调

我们先来看一下编写AJAX编码经常遇到的几个问题: 1.由于AJAX是异步的,所有依赖AJAX返回结果的代码必需写在AJAX回调函数中.这就不可避免地形成了嵌套,ajax等异步操作越多,嵌套层次就会越深,代码可读性就会越差. $.ajax({ url: url, data: dataObject, success: function(){ console.log("I depend on ajax result."); }, error: function(){} }); consol

jQuery源码笔记——回调对象

回调对象是一个多用途的回调列表对象,提供了强大的的方式来管理回调函数列表. 最简单的缓存对象 function Callbacks(){ var list = [], self = { add: function(fn){ list.push(fn); }, remove: function(fn){ var index; if((index = list.indexOf(fn)) > -1){ list.splice( index, 1 ); } }, fire: function(value

.Net之使用Jquery Ajax通过FormData对象异步提交图片文件到服务端保存并返回保存的图片路径

前言: 首先对于图片上传而言,在我们的项目开发中可以说出现的频率是相当的高的.这篇文章中,我将要描述的是在我们.Net中如何使用Jquery Ajax通过FormData对象异步提交图片文件到后台保存,并返回保存的图片路径展示出图片,实现一个无刷新的异步图片上传的过程,当然这里我讲解的是单张图片的保存过程,对于多图片上传的话其实我们只需要在type='file'文本框中加上一个multiple可多选,然后获取input中的文件数组遍历向后台提交感兴趣的话可以尝试,不过下一篇博客将会讲解如何使用L

jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)

转载http://www.cnblogs.com/aaronjs/p/3356505.html Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图************************** **********************源码解析********************** 因为callback被剥离出去后,整个deferred

最细的实现剖析:jQuery 2.0.3源码分析Deferred

Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html **构建Deferred对象时候的流程图** **源码解析** 因为callback被剥离出去后,整个deferred就显得非常的精简 jQuery.extend({ Deferred:function(){} when:function() )}对于extend的继承这个东东,在之前就提及过jquery如何处理内部jquery与init相互引用this的问题 对于JQ的

jQuery:在一个回调中处理多个请求

我曾经为Mozilla Developer Network 开发一个新功能,它需要加载一个基本的脚本文件的同时加载一个JSON请求.因为我们使用的是jQuery,意味着要使用 jQuery.getScript和jQuery.getJSON.我知道这两者都是异步的并返回一个Deferred(jQuery中的Promise模式实现, 参见: deffered object)对象,因此我想知道能不能在一个回调里按顺序请求它们,就像多数的JavaScript加载器那样(如curljs ).我很幸运,使用