zoukankan      html  css  js  c++  java
  • 利用 Jquery Deferred 异步你的程序

    最近在做公司QA系统改造时,有这样的一个场景.

    QA系统中有些数据项需要从JIRA平台(一个国外项目与事务跟踪工具)中获取,JIRA平台提供了很完善的Rest API.

    现在的要求是,在QA系统中提交项目时,必须先从JIRA平台获取很多的数据项,每次请求的Rest API都不一样,

    同时必须等所有请求都成功返回数据后才能提交项目.

    因为之前对Jquery Deferred有过研究,发现这个场景用它来实现再合适不过了.

    这里对Jquery Deferred不做过多讲解了,不了解的同学可以先看下面的文章.

    http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

    http://www.cnblogs.com/justany/archive/2013/01/20/2867444.html

    好了,现在让我们来模拟上面的场景.(文章最后有完整DEMO下载)

    假设我们获取数据项的请求全都由JqueryHandler.ashx来处理,在handler里面用Thread.Sleep()来模拟请求Rest API时的网络延迟.

     public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "application/json";
    
                string action = context.Request.Form["Action"];
                //用Thread.Sleep()模拟请求Rest API时的网络延迟
                switch (action)
                {
                    case "delay1Seconds":
                        Thread.Sleep(2000);
                        WriteSuccess(context, action, "2");
                        break;
                    case "delay2Seconds":
                        Thread.Sleep(1000);
                        WriteSuccess(context, action, "1");
                        break;
                    case "delay3Seconds":
                        Thread.Sleep(3000);
                        WriteSuccess(context, action, "3");
                        break;
                    default:
                        break;
                }
            }
    
            public void WriteSuccess(HttpContext context, string action, string seconds)
            {
                //输出JSON结果
                string index = context.Request.Form["Index"];
                string json = "{"flag":0,"msg":" + seconds + ","Index":" + index + "}";
                context.Response.Write(json);
            }

    数据服务端模拟好了之后,接下来让我们来发出获取数据项的请求.

        <script src="Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
        <script type="text/javascript">
            $(function () {
    
                $("#btn_Request").click(
                    function () {
                        $("#div_Content").html("");
    
                        //模拟请求Handler地址
                        var requestUrl = "JqueryHandler.ashx";
    
                        //ajax请求 action名称数组
                        var requestInfoArr =
                        [
                          { Action: "delay1Seconds" },
                         { Action: "delay2Seconds" },
                         { Action: "delay3Seconds" }
                        ];
    
                        //用于保存Jquery Defered对象
                        var deferredOBJ = [];
    
                        //创建3个 Jquery Deferred 对象
                        //与3个对 JqueryHandler.ashx 的异步请求一 一对应
                        for (var i = 0; i < requestInfoArr.length; i++) {
                            deferredOBJ[i] = $.Deferred();
    
                            var jsonData = requestInfoArr[i];
    
                            //记录当前ajax请求的索引,方便后面找到对应的Jquery Deferred对象
                            jsonData.Index = i;
    
                            //发出ajax请求
                            $.ajax({
                                type: "POST",
                                dataType: "json",
                                url: requestUrl,
                                data: jsonData,
                                success: function (data, statu) {
                                    //flag为0时表示请求成功
                                    if (data.flag == 0) {
                                        var result = requestInfoArr[data.Index].Action + " 请求成功,耗时:" + data.msg + "秒";
                                        $("#div_Content").append($("<p/>").text(result));
    
                                        //根据前面传过去的索引找到对应Deferred对象,将状态改成resolve(表示成功)
                                        deferredOBJ[data.Index].resolve();
                                    } else {
                                        // 如果请求出错,将状态改成reject (表示失败)
                                        //这里调用reject()后,会立即执行下面的fail()函数
                                        deferredOBJ[data.Index].reject(data.msg);
                                    }
                                },
                                error: function (data, statu) {
                                    alert("ajax请求获取数据失败!");
                                }
                            });
                        }
    
                        //使用$.when() 来控制3个异步请求的流程,保证所有异步请求都完成后再执行done函数
                        $.when(deferredOBJ[0], deferredOBJ[1], deferredOBJ[2])
                         .done(function () {
                             var result = "所有请求完成...";
                             $("#div_Content").append($("<p/>").text(result));
                         })
                         .fail(function (error) {
                             alert("从JIRA获取度量项数据失败, 请重试");
                         });
    
                    });
    
            });
        </script>

    这里的巧妙之处在于 jsonData.Index = i;  这句代码,不然要就要写3个ajax请求,代码会显得臃肿.

    如果不记录当前请求索引的话,后面的success,error函数就无法找到对应的Deferred对象来改变状态.

    可能大家会问,为什么不用deferredOBJ[i]来获取,这是因为请求都是异步的,在success,error函数里来获取 i 永远都是2(因为requestInfoArr.length是2).

    让我们来验证一下这3个ajax请求是不是都是异步执行的.

    用firebug可以看到3个ajax请求是同时发出的,这样3个请求只花了3.09s.

    如果3个ajax请求是顺序执行的话就需要花费 2.03s+1.06s+3.09s=6.18s, 使用jquery deferred节约了一倍的时间.

    最后附上程序运行截图和DEMO程序:

    完整DEMO下载:Jquery Deferred

     
  • 相关阅读:
    如何用SQL命令修改字段名称
    两个sql server 2000的通用分页存储过程
    Tomcat 6 连接 MS SQL 2005
    log4net 配置与应用
    如何去除Google搜索结果病毒提示
    Windows 2003远程桌面连接数限制
    ntext replace sql
    FCKeditor详细的设置
    SQL Server 自增字段归零等问题
    SQLServer2005数据库还原到SQLServer2000
  • 原文地址:https://www.cnblogs.com/RockLi/p/3228116.html
Copyright © 2011-2022 走看看