zoukankan      html  css  js  c++  java
  • jquery 之 Deferred 使用

    Deferred是jquery的promise接口的实现。他是非同步操作的通用接口,可以看作是完成一个任务之后再执行另外一个任务。

    观察者模式是开发中经常使用的模式,这个模式由两个主要部分组成:主题和观察者。通过观察者模式,实现主题和观察者的解耦.

    主题负责发布内容,而观察者则接收主题发布的内容。

    在 jQuery 中,实现观察者模式的就是 Deferred 了,我们先看它的使用。

    使用 Deferred

    // 定义主题
    var subject = (function(){
        var dfd = $.Deferred();
        
        var task = function()
        {
            // 发布内容
            dfd.resolve("Alice");
        }
        
        setTimeout( task, 3000);
        
        return dfd.promise();
    })();
    
    // 两个观察者
    var fn1 = function(content){
        console.log("fn1: " + content );
    }
    
    var fn2 = function(content){
        console.log("fn2: " + content );
    }
    
    // 注册观察者
    $.when( subject )
    .done( fn1 )
    .done( fn2 );

    在 jQuery 中,甚至可以提供两个主题同时被观察, 需要注意的是,要等两个主题都触发之后,才会真正触发,每个观察者一次得到这两个主题,所以参数变成了 2 个。

    // 定义主题
    var subjectAlice = (function(){
        var dfd = $.Deferred();
        
        var task = function()
        {
            // 发布内容
            dfd.resolve("Alice");
        }
        
        setTimeout( task, 3000);
        
        return dfd.promise();
    })();
    
    var subjectTom = (function(){
        var dfd = $.Deferred();
        
        var task = function()
        {
            // 发布内容
            dfd.resolve("Tom");
        }
        
        setTimeout( task, 1000);
        
        return dfd.promise();
    })();
    
    // 两个观察者
    var fn1 = function(content1, content2){
        console.log("fn1: " + content1 );
        console.log("fn1: " + content2 );
    }
    
    var fn2 = function(content1, content2){
        console.log("fn2: " + content1 );
        console.log("fn2: " + content2 );
    }
    
    // 注册观察者
    $.when( subjectAlice, subjectTom )
    .done( fn1 )
    .done( fn2 );

    $.when()方法

    $.when()接受多个deferred对象作为参数,当它们全部运行成功后,才调用resolved状态的回调函数,但只要其中有一个失败,就调用rejected状态的回调函数。它相当于将多个非同步操作,合并成一个。

    例如:

    $.when(
        $.ajax( "/main.php" ),
        $.ajax( "/modules.php" ),
        $.ajax( "/lists.php" )
    ).then(successFunc, failureFunc);

    上面代码表示,要等到三个ajax操作都结束以后,才执行then方法指定的回调函数。

    when方法里面要执行多少个操作,回调函数就有多少个参数,对应前面每一个操作的返回结果。

    例如:

    $.when(
        $.ajax( "/main.php" ),
        $.ajax( "/modules.php" ),
        $.ajax( "/lists.php" )
    ).then(function (resp1, resp2, resp3){
        console.log(resp1);
        console.log(resp2);
        console.log(resp3);
    });

    上面代码的回调函数有三个参数,resp1、resp2和resp3,依次对应前面三个ajax操作的返回结果。

    then()方法

    then()的作用也是指定回调函数,它可以接受三个参数,也就是三个回调函数。第一个参数是resolve时调用的回调函数,第二个参数是reject时调用的回调函数,第三个参数是progress()方法调用的回调函数。

    代码如下:
    deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

    then()和done()的区别

    在jQuery 1.8之后,then()返回一个新的deferred对象,而done()返回的是原有的deferred对象

    如果then()指定的回调函数有返回值,该返回值会作为参数,传入后面的回调函数。

    例如:如下代码:

    var defer = jQuery.Deferred();
    defer.done(function(a,b){
                return a * b;
    }).done(function( result ) {
                console.log("result = " + result);
    }).then(function( a, b ) {
                return a * b;
    }).done(function( result ) {
                console.log("result = " + result);
    }).then(function( a, b ) {
                return a * b;
    }).done(function( result ) {
                console.log("result = " + result);
    });
    defer.resolve( 2, 3 );

    返回的结果为:

    result = 2 
    result = 6 
    result = NaN 

    分析:

    1)上面的第一个result是第一个result的最后一个done()的输出,前一个done的return不会传递到这里,所以result是resolve的第一个参数
    2)第二个result是第二个deferred的输出,第一个then所带的function的输入,传入第二个deferred,因此第五个done能够接受到2*3的result。
    3)第三个result是第三个deferred的输出,第二个then执行时,只有a,没有b(上一个then执行时返回的是a*b,所以再第三个then执行时只有a,没有b),所以result是NaN。


    综合例子如下:
        var requestInfo = function() {
            var defered = $.Deferred();
            var url = "https://api.ffan.com/activity/v1/homepage/index";
            $.ajax(url, {
                dataType: "jsonp",
                jsonp: "callback",
                timeout: 5000,
                data: {
                    type: "cityList"
                }
            }).then(function(response) {
                if (response && response.data && response.data[0]) {
                    defered.resolve(response.data[0].cityList);
                }
            })
            return defered.promise();
        }
    var cityInfo = function(result) {
            var list = _.groupBy(result, function(city) {
                return city.cityPinYin.charAt(0).toUpperCase();
            });
    
            _.each(list,function(city,key){
                console.log(key);
                _.each(city,function(item,index){
                    console.log("item.cityId="+item.cityId);
                    console.log("item.cityName="+item.cityName);
                })
            })
    
            //获取第一条数据的cityId
            var cityId=list["A"][0].cityId;
    
    //返回值,供下一个then调用
    return { id:cityId } }
     var info=function(result){
            var id=result.id;//上一个then返回的值
            console.log("cityid="+id);
            return true;
        }

    调用:

     $.when(requestInfo()) 
            .then(cityInfo)
            .then(info);
  • 相关阅读:
    线性动力学变分原理基础 Part1
    对分析动力学的一些理解
    Matlab数值求解超越方程的根
    FORTRAN数值求超越方程的根
    vim 基础操作
    a simple vim set for fortran
    g95 ld: cannot find crt1.o: No such file or directory
    ug中英文对照
    autocad一些快捷键和命令
    列选主元的高斯消元法的Fortran程序
  • 原文地址:https://www.cnblogs.com/alice626/p/5581395.html
Copyright © 2011-2022 走看看