回调列表

jQuery的应用

在jQuery1.5之前 ajax的api如下

$.ajax({
    url: '',
    success:function(data, status, xhr){...},
    error:function(xhr, status, errMsg){...},
    complete:function(xhr, status){...}
})

而在1.5之后加入了队列

$.ajax(url)
    .done:function(data, textStatus, jqXHR){...} //对应success
    .done:function(data, textStatus, jqXHR){...}
    .fail: function(jqXHR, textStatus, errorThrown){...} 
    .fail: function(jqXHR, textStatus, errorThrown){...}
    .complete:function(jqXHR, statusText){...}
    .complete:function(jqXHR, statusText){...}
})

简单来说就是可以定义多个成功/失败的事件,然后按顺序执行

Callbacks函数

jQuery.Callbacks( options )

options可以多选的四个值

  1. once: 回调列表只能被fire一次
  2. memory: 记得上次触发回调函数列表的参数,之后添加任何回调函数都将用记录的参数值立即回调
  3. 确认一个回调函数智能被添加一次
  4. 当某个回调函数返回false终端执行

可以在https://api.jquery.com/jQuery.Callbacks/里查看更多demo方便理解

DEMO

说实话,使用和理解之前需要好好研究一下他用法

辅助型输出

function fn1( value ) {
  console.log( "fn1 says: " + value );
  return false; //为了演示stopOnFalse,不影响其他属性
}

function fn2( value ) {
  console.log( "fn2 says: " + value );
}

没参数的情况

var callbacks = $.Callbacks();
callbacks.add( fn1 );

callbacks.fire( "foo!" );// fn1 says: foo!

callbacks.add( fn2 );

callbacks.fire( "bar!" );// fn1 says: bar! fn2 says: bar!

callbacks.remove( fn2 );

callbacks.fire( "foobar" ); //fn1 says: foobar

once

var callbacks = $.Callbacks( "once" );
callbacks.add( fn1 );
callbacks.fire( "foo" ); //fn1 says: foo
callbacks.add( fn2 );
callbacks.fire( "bar" );
callbacks.remove( fn2 );
callbacks.fire( "foobar" );

memory

var callbacks = $.Callbacks( "memory" );
callbacks.add( fn1 );
callbacks.fire( "foo" ); //fn1 says: foo
callbacks.add( fn2 ); //fn2 says: foo
callbacks.fire( "bar" ); //fn1 says: bar fn2 says: bar
callbacks.remove( fn2 ); 
callbacks.fire( "foobar" );//fn1 says: foobar

unique

var callbacks = $.Callbacks( "unique" );
callbacks.add( fn1 );
callbacks.fire( "foo" ); //fn1 says: foo
callbacks.add( fn1 ); // Repeat addition
callbacks.add( fn2 );
callbacks.fire( "bar" ); //fn1 says: bar fn2 says: bar
callbacks.remove( fn2 );
callbacks.fire( "foobar" ); //fn1 says: foobar

stopOnFalse

var callbacks = $.Callbacks( "stopOnFalse" );
callbacks.add( fn1 );
callbacks.fire( "foo" ); //fn1 says: foo
callbacks.add( fn2 );
callbacks.fire( "bar" ); //fn1 says: bar
callbacks.remove( fn2 );
callbacks.fire( "foobar" );//fn1 says: foobar

API

  1. add(callbacks)
  2. remove(callbacks)
  3. has(callback) //判断函数是否在回调列表中
  4. empty() /清空回调队列

结构

jQuery.Callbacks = function( options ) {
    firing, //是否正在执行回调函数
    memory, //最后一个被fire时的参数,从queue属性了shift()出来的
    fired, //是否正在fired
    locked,//改函数队列是否已经锁定,不被执行 手动lock()和once时fire一次时为true
    list = [], //真实的回调队列,里面存储着用户add进来的函数
    queue = [], //存储着fire时的参数,queue里面也是数组[0: context,1: 具体fire时的参数]
    firingIndex = -1, //记录当前队列正在执行第几个回调函数
    fire(),
    self = {
        add(callbacks),//添加一个或一组回调函数
        remove(), //删除一个或一组回调函数
        has( [fn] ), //当fn为空时,判断是否有回调列表,不为空时,判断fn是否在回调列表中
        empty(), //清空list(真实回调队列)
        disable(),//disable掉.add()和.fire(),真正的disable,因为当memory模式时,add也会触发.fire()
        disabled(),//是否disable
        lock(),//锁定队列,disable掉.fire()
        locked(),//判断是否回调队列已经被锁定
        fireWith( context, args ), //触发回调队列
        fire(args),//触发回调队列
        fired(), //是否正在触发
    }

}

重点

memory模式下记录参数

只会记住上一次fire的参数

var callbacks = $.Callbacks( "memory" );
callbacks.add( fn1 ); 
callbacks.fire( "foo" );  //fn1 says: foo
callbacks.fire( "foo2" ); //fn1 says: foo2
callbacks.add( fn2 ); //fn2 says: foo2

通过queue记录最后一个fire的参数

以下代码被我修饰过,去掉了和memory无关的代码

var memory, //记录最后一个fire的参数
    queue = [], //存储当时fire时的参数
    list = [],//存储真实add进来的行数
    fire = function() { //内部fire函数
        ...
        for ( ; queue.length ; firingIndex = -1) {
            memory = queue.shift()
            while( ++firingIndex < list.length)  {
               list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ]
            }
        }
        ...
    },
    self = {
        add: function (){
            if ( memory && !firing ) {
                firingIndex = list.length - 1;
                queue.push( memory );
            }

            ( function add( args ) { //属性内定义方法比较优秀的写法 
                jQuery.each( args, function( _, arg ) {
                    if ( jQuery.isFunction( arg ) ) {
                        if ( !options.unique || !self.has( arg ) ) { //如果是unique的防重复
                            list.push( arg );
                        }
                    } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {

                        // Inspect recursively 递归检查
                        add( arg );
                    }
                } );
            } )( arguments );

            if ( memory && !firing ) {
                fire();
            }            
        },
        fireWith: function( context, args ) { //调用.fire()实际调用的方法
            var args = [ context, args ]
            queue.push (args)
            fire()//内部的fire函数
        }
    }
© 404mzk all right reserved,powered by Gitbookhttp://blog.404mzk.com 该文件修订时间: 2017-03-09 12:51:57

results matching ""

    No results matching ""