美文网首页
Deferred对象

Deferred对象

作者: 我_巨可爱 | 来源:发表于2017-12-01 14:59 被阅读0次

jQuery.Deferred 对象

实例上的方法

一共14个

  1. deferred.resolve(args) / defered.resolveWith(context,args)
  2. deferred.reject(args) / deferred.rejectWith(contex,args)
  3. deferred.done()
  4. deferred.fail()
  5. deferred.always()
  6. deferred.notify() 当使用的时候,只要deferred对象的状态没有改变为resolvedrejected,可以访问通过deferred.thendeferred.progress添加的函数。否则,不起作用。
  7. deferred.notifyWith(context, ['args])
  8. deferred.progress() 添加回掉函数列,属于notify一列。当deferred对象是resolved或者rejected,无法添加。
  9. deferred.promise() // 返回的对象是deferred子集,只能添加,不能改变状态。
  10. deferred.state() // 返回状态字符串,pendingresolvereject
  11. deferred.catch()
  12. deferred.then()

注意点

  1. resolve 之后,无论是 done 还是 then 方法添加函数,都会自动执行,并且,参数都是 resolve 参数
  2. 但是,resolve 之后,done/then 的链式操作上的 done/then 是不能收到 resovle 参数的,收到的是上一个的返回值

其他相关方法

  1. $.when(deferreds) 传入延迟对象(通常表示异步事件),返回Promise 对象(延迟对象的一个子集)。然后调用其他的方法
  • 比如setTimeout是一个异步事件,需要改装成deferred对象之后,传入
  1. $elem.promise() 主要用在动画上
// setTimeout 与 deferred
function wait () {
    var def = $.Deferred();
    setTimeout(function () {
        console.log('finished!');
        def.resolve();
    },2000)
    return def;
  }
// 使用 when 之后返回的是 promise 对象,不能改变状态,相对于`deferred`对象,更加安全
  $.when(wait())
    .done(function () {console.log("成功")})
    .fail(function () {console.log("错误")})

Deferred 源码分析

框架

jQuery.extend({
    Deferred: function (func) {
        // 四个重要的变量
        var tuples,
            state = "pending",
            promise = {},
            deferred = {};
        // 将 promise 对象整合到 deferred 对象上
        promise.promise(deferred);
        // 如果使用构造函数时,有参数`func`,就要使用`call`调用
        if (func) {
            func.call(deferred, deferred);
        }
        // 返回对象
        return deferred;
    }
})

初始化

var tuples = [
    [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
    [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
    [ "notify", "progress", jQuery.Callbacks("memory") ]
];
jQuery.each(tuples, function (i, tuple) {
    var list = tuple[2],
        stateString = tuple[5];
    // 其实 `done`等方法实质上是回调对象的`add`方法
    pormisep[tuple[1]] = list.add;
    if (stateString) {
        // 在函数列队中添加三个初始化函数
        /*
            1. 改变状态字符串
            2. 使对立面的函数队列无效
            3. 锁住`progress`函数队列
        */
        list.add(function () {state = stateString;},tuples[3 - i][2].disable, tuples[0][2].lock);
    }
    // `resolve`等方法内部使用的是`cb.fireWith()`
    deferred[tuple[0]] = function () {
        deferred[tuple[0] + "With"](this === deferred ? undefined : this, arguments);
        return this;
    }
    // `resolveWith`等方法内部使用的是`cb.fireWith()`
    deferred[tuple[0] + "With"] = list.fireWith;
});

then方法

var promise = {
    then: function ( /* fnDone, fnFail, fnProgress */ ) {
        var fns = arguments;
        // 返回的是新 deferred 对象的 promise 对象
        // newDefer 就是这里新生成的 deferred 对象
        return jQuery.Deferred(function (newDefer) {
            jQuery.each(tuples, function (i, tuple) {
                // action 就是 触发方法名
                // fn 就是需要添加到不同序列的函数
                var action = tuple[0],
                    fn = jQuery.isFunction(fns[i]) && fns[i];
                // deferred 相应的序列上添加 这个匿名函数
                deferred[tuple[1]](function () {
                    // 这里的 arguments 应该是 匿名函数的
                    // 记得 callbacks 中 memory, 匿名函数即使是没有参数,在 memory 的情况下是可能有的
                    var returned = fn && fn.apply(this, arguments);
                    // 判断返回值,返回值如果是 deferred 对象
                    if (returned && jQuery.isFunction(returned.promise)) {
                        // 如果返回的是 deferred 对象,链式操作,需要等到 返回的deferred对象改变
                        // 那么就将点燃的权利交给 returned 的序列中 
                        returned.promise()
                            .done(newDefer.resolve)
                            .fail(newDefer.reject)
                            .progress(newDefer.notify);
                    } else {
                        // 如果返回值只是非 deferred 对象
                        // this 是 newDefer
                        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;
    }
}

Deferred 的 resolve 注意事项

  1. 当延迟对象被 resolved 时,任何通过 deferred.thendeferred.done添加的 doneCallbacks,都会被调用
  2. 回调函数的执行顺序和它们被添加的顺序是一样的
  3. 传递给 deferred.resolve() 的 args 参数,会传给每个回调函数
  4. 当延迟对象进入 resolved 状态后,再添加的任何 doneCallbacks,当它们被添加时,就会被立刻执行,并带上传入给resolve的参数
  5. 但是,resolve 之后,done/then 的链式操作上的 done/then 是不能收到 resovle 参数的

Deferred 中 promise 对象

  1. 其实donefailprogress方法属于promise对象
  2. promise对象,由属于deferred对象,deferred对象上有resolverejectnotify等方法
  3. promise对象上promise方法,是将传入对象进行包裹,然后返回

相关文章

  • Deferred对象

    Deferred对象 什么是Deferred对象?Deferred对象是从jQuery 1.5.0版本开始引入的一...

  • jQuery.deferred详解

    deferred是什么? deferred 翻译为推迟,在jQuery 1.5中引入的Deferred对象是通过调...

  • deferred对象的方法

    (1)$.Deferred()生成一个deferred对象。(2)deferred.done()指定操作成功时的回...

  • deferred对象学习(上)

    一、deferred对象是什么? defer:"延迟",所以deferred对象的含义就是"延迟"到未来某个点再执...

  • deferred对象

    最近做项目,调用后端接口,需要等到2个ajax返回再执行另一个ajax,首先想到的是使用promise,但是考虑...

  • Deferred对象

    jQuery在1.5之后引进了Deferred对象,主要是对操作时间很长的方法回调提供一个简单、直观的解决方案。之...

  • Deferred对象

    jQuery.Deferred 对象 实例上的方法 一共14个 deferred.resolve(args) / ...

  • jQuery-v2.0.3源码浅析05-when

    jQuery提供的when方法可以管理多个Deferred对象。打比方说如果你创建了多个Deferred对象,这个...

  • jQuery的deferred对象详解 作者:阮一峰 一、什么是deferred对象? 开发网站的过程中,我们经常...

  • jQuery-v2.0.3源码浅析04-Deferred

    接下来我们来看下jQuery的延迟对象Deferred。我们前面讲过Callbacks函数,其实Deferred就...

网友评论

      本文标题:Deferred对象

      本文链接:https://www.haomeiwen.com/subject/ibswvxtx.html