• 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,当其所有都完成时候触发回调。

      

      

  • 相关阅读:
    多通道 移位寄存器 verilog
    modelsim-altera IP核仿真
    modelsim-altera
    YUV视频显示软件+源码
    opencl教程
    使用VisualStudio读写NI FPGA板卡实例(基于FPGA Interface C API Generator)
    Visual Studio编译与调用DLL方法
    NI FPGA板卡程序设计概述
    LabVIEW中使用GPU进行高性能计算
    Windows平台编程涉及的函数
  • 原文地址:https://www.cnblogs.com/pfzeng/p/4478571.html
Copyright © 2020-2023  润新知