码迷,mamicode.com
首页 > Web开发 > 详细

jQuery源码研究分析学习笔记-jQuery.deferred()(12)

时间:2016-08-23 13:23:52      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:

JS是单线程语言,把每一件事情(包括GUI事件和渲染)都放在一个线程里来处理是一个很好的程序模型,因为这样就无需再考虑线程同步这些复杂问题。

但js暴露了应用开发中的一个严重问题,单线程环境看起来对用户请求响应迅速,但是当线程忙于处理其它事情时,就不能对用户的鼠标点击和键盘操作做出响应。
jQuery.deferred异步模型提供了一个抽象的非阻塞的解决方案。

jQuery.deferred()在jQ中常用的有:

  1. promise
  2. Ajax模块
  3. 动画模块
  4. DOM ready
    jQuery.Deferred(func)在jQuery.Callbacks(flags)的基础上,为回调函数增加了状态,提供了多个回调函数列表。可以通过调用方法deferred.done/fail/progress/then/always()添加成功调回调函数、失败回调函数、消息回调函数到对应的成功、失败、消息回调函数列表中,并且可通过调用方法derred.resolve/resolveWith/rejectWith/notify/notifyWith()分别触发成功、失败、消息回调函数列表。
    异步队列有三种状态:pending,resolved,rejected分别是待定、成功、失败。
    异步队列的方法列表如下:

    技术分享
    技术分享

jQuery.Deferred(func)创建异步队列步骤:

  1. 创建成功、失败、消息回调函数列表,设置初始状态为pending(待定);
  2. 创建异步队列的只读副本promise,其中包含了方法done()、fail()、progress()、state()、isResolved()、isRejected()、then()、always()、pipe()、promise()
  3. 定义异步队列deferred
  4. 如果传入函数参数func,则调用
  5. 返回异步队列deferred
jQuery.extend({

    Deferred: function( func ) {

        //成功回调函数列表,once表示回调函数列表只能被触发一次,memory表示会记录上一次触发回调函数列表时的参数,触发后添加的任何回调函数都将用记录的参数值立即调用
        var doneList = jQuery.Callbacks( "once memory" ),

            //失败回调函数列表
            failList = jQuery.Callbacks( "once memory" ),

            //消息回调函数
            progressList = jQuery.Callbacks( "memory" ),
            //初始状态,在调用方法deferred.resolve()或deferred。resolveWith()后被设置为字符串“resolved”,表示成功状态,调用方法deferred.reject()或deferred.resolveWith()后被设置为字符串“rejected”,表示失败状态
            state = "pending",


            lists = {
                resolve: doneList,
                reject: failList,
                notify: progressList
            },
            //异步队列的只读副本,前三个是引用对应的回调函数列表的方法callbacks.add()
            promise = {
                done: doneList.add,
                fail: failList.add,
                progress: progressList.add,

                //返回状态
                state: function() {
                    return state;
                },

                // Deprecated
                isResolved: doneList.fired,
                isRejected: failList.fired,

                //用户将回调函数同事添加到成功回调函数列表doneList和失败回调函数列表failList,保存两份引用,当异步队列处于成功或失败状态时被调用
                then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
                    //采用链式语法依次调用方法done(),fail(),progress()逐个添加回调函数,并返回this以绩效支持链式语法
                    deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
                    return this;
                },
                always: function() {
                    deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
                    return this;
                },

                //用来过滤当前异步队列的状态和参数,并返回一个新的异步队列的只读副本。当前异步队列被触发时,过滤函数将被调用并把返回值给只读副本
                pipe: function( fnDone, fnFail, fnProgress ) {
                    return jQuery.Deferred(function( newDefer ) {
                        jQuery.each( {
                            done: [ fnDone, "resolve" ],
                            fail: [ fnFail, "reject" ],
                            progress: [ fnProgress, "notify" ]
                        }, function( handler, data ) {
                            var fn = data[ 0 ],
                                action = data[ 1 ],
                                returned;
                            if ( jQuery.isFunction( fn ) ) {
                                deferred[ handler ](function() {
                                    returned = fn.apply( this, arguments );
                                    if ( returned && jQuery.isFunction( returned.promise ) ) {
                                        returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
                                    } else {
                                        newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
                                    }
                                });
                            } else {
                                deferred[ handler ]( newDefer[ action ] );
                            }
                        });
                    }).promise();
                },
                // Get a promise for this deferred
                // 用于返回当前异步队列的只读副本,或为一个javascript对象增加只读副本中的方法并返回。
                promise: function( obj ) {

                    //如果没有传入参数,则返回当前异步队列的只读副本promise
                    if ( obj == null ) {
                        obj = promise;
                    } else {
                    //若传入了参数obj,则把只读副本promise中的方法添加到参数obj中,从而似的参数obj具有异步队列行为,但是只包含了添加回调函数和判断状态的方法
                        for ( var key in promise ) {
                            obj[ key ] = promise[ key ];
                        }
                    }
                    return obj;
                }
            },

            //异步队列把只读副本promise中的方法添加到异步队列deferred中
            deferred = promise.promise({}),
            key;

        //为异步队列添加触发成功、失败、消息回调函数列表的方法
        for ( key in lists ) {
            deferred[ key ] = lists[ key ].fire;
            deferred[ key + "With" ] = lists[ key ].fireWith;
        }

        // 添加设置状态的回调函数
        deferred.done( function() {
            state = "resolved";
        }, failList.disable, progressList.lock ).fail( function() {
            state = "rejected";
        }, doneList.disable, progressList.lock );

        // 若传入函数参数func,则执行
        if ( func ) {
            func.call( deferred, deferred );
        }

        // 返回异步队列deferred
        return deferred;
    },  
});

jQuery源码研究分析学习笔记-jQuery.deferred()(12)

标签:

原文地址:http://blog.csdn.net/lfcss/article/details/52287665

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!