什么是deferred对象

deferred对象是一个延时对象,函数延迟到某个点才开始执行,改变执行状态的方法有两个(成功:resolve和失败:reject),分别对应两种执行回调(成功回调函数:done和失败回调函数fail)

var wait = function() {
        var der = $.Deferred(); //创建deferred对象
        var test = function(){
            console.log("111");
            der.resolve("222") 
        test()
        return der
    $.when(wait())  //$.when()参数里面必须是deferred对象
        .done(function(data){ 
            console.log("执行成功",data)    
        .fail(function(){
            console.log("执行失败")
//打印结果:
//111
//222 ys
复制代码

实现

Defferred的实现跟jQuery内部Callbacks函数密不可分 Callbacks源码分析 ,要用到其内部的fireWith函数,该函数主要用于控制参数传递以及执行list中的所有回调函数。

Deferred: function(func){
    //tuples数组储存延迟对象的不同状态信息描述
    var tuples = [
        ["resolve", "done", jQuery.Callbacks("once memory")],
        ["reject", "fail", jQuery.Callbacks("once memory")]
    promise = {
        then(){
        promise(obj){
            return obj != null ? jQuery.extend(obj, promise) : promise
    //延迟对象
    deferred = {}
    tuples.forEach((tuple, i)=>{
        //创建Callbacks队列函数,list=jQuery.Callbacks("once memory")
        var list = tuple[2]
        //扩展promise对象,promise[ done | fail ] = list.add
        //调用done,fail,progress会给队列里面添加处理函数
        promise[tuple[1]] = list.add
        //给deferred扩展resolve,reject
        // deferred.resolve = function() { deferred.resolveWith(...) }
        // deferred.reject = function() { deferred.rejectWith(...) }
        deferred[tuple[0]] = function(){
            //给fireWith传递参数,指定this
            deferred[tuple[0] + "With"](this === deferred ? promise : this , arguments)
            return this
        deferred[tuple[0] + "With"] = list.fireWith
    //扩展deferred属性,相当于合并promise跟deferred,
    //基本数据类型传参是按值传递,不会改变原对象。引用数据类型按对象传递、按对象共享传递,该方法会改变实参deferred
    // deferred对象上面包含 resolve | reject | promise | done | fail | rejectWith | resolveWith 这些方法
    promise.promise(deferred)
    return deferred
//接受延迟对象的回调函数,返回的是promise对象
when(deferred){
    return deferred.promise()
复制代码

以上基本能实现deferred对象功能,包含resolve()及reject两个处理函数

deferred对象包含的方法包括 resolve | reject | promise | done | fail | rejectWith | resolveWith

when()函数返回promise对象,其包括的方法有 done | fail | promise

当执行deferred对象的resolve()方法,相当于执行了deferred.resolveWith(),也就是Callbacks里面的fireWith函数,执行Callbacks队列函数的所有回调函数。deferred.resolve() -> deferred.resolveWith() -> list.fireWith() -> list.fire()

回调函数添加进入Callbacks队列函数是通过 promis.done(回调函数) 添加,promise[tuple[1]] = list.add, 由于创建Callbacks传入了memory参数,jQuery.Callbacks("once memory"),它会在添加函数的同时执行Callbacks队列函数

var wait = function() {
    var der = $.Deferred(); //创建deferred对象
    var test = function(){
        console.log("111");
        der.resolve("222") //执行Callbacks队列函数添加回调函数
    test()
    return der
$.when(wait())  //$.when()参数里面必须是deferred对象,返回的是promise对象
    .done(function(data){   //向Callbacks队列函数添加回调函数,并执行队列函数
        console.log("执行成功",data)
    .fail(function(){
        console.log("执行失败")
//打印结果:
//111
//222 ys
复制代码

以上便基本实现了Deferred对象,当然Deferred本身还不仅仅是这些,Deferrred最复杂深奥的代码在promise.then里面,本文没有分析,有空再深入

  •