利用 Jquery Deferred 异步你的程序

标签: 利用 jquery deferred | 发表时间:2013-09-04 17:55 | 作者:
出处:http://www.iteye.com

最近在做公司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

 


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [利用 jquery deferred] 推荐:

利用 Jquery Deferred 异步你的程序

- - ITeye博客
最近在做公司QA系统改造时,有这样的一个场景.. JIRA平台(一个国外项目与事务跟踪工具)中获取,JIRA平台提供了很完善的Rest API.. 现在的要求是,在QA系统中提交项目时,必须先从JIRA平台获取很多的数据项,每次请求的Rest API都不一样,. 同时必须等所有请求都成功返回数据后才能提交项目..

jQuery的deferred对象详解

- 郑小东 - 阮一峰的网络日志
jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. 这个功能很重要,未来将成为jQuery的核心方法,它彻底改变了如何在jQuery中使用ajax. 为了实现它,jQuery的全部ajax代码都被改写了.

jQuery中利用JSONP解决AJAX跨域问题

- - 蓝飞技术博客
跨域的解决方案有多种,其中最常见的是使用同一服务器下的代理来获取远端数据,再通过ajax进行读取,而在这期间经过了两次请求过程,使得获取数据的效率大大降低,这篇文章蓝飞就为大家介绍一下解决跨域问题的一种比较通用的方案——JSONP. 简单的来说,出于安全方面的考虑,页面中的JavaScript无法访问其他服务器上的数据,即“同源策略”.

利用jQuery和HTML5实现无刷新Ajax风格的表单

- - CSDN博客推荐文章
        利用jQuery我们能够做出一些相当震撼的网页效果. jQuery的出现使DOM的操作更加的简单易用. 下面的教程展示了如何利用jQuery创建一个HTML5效果的邀请表格,同时实现表格内容的检查功能.         首页的格式必须是HTML5的格式.         接下来添加jQuery库,将如下代码添加到标签之前:.

JQuery 选择器

- - CSDN博客Web前端推荐文章
}

点击我

.    像上面这样把JavaSript代码和HTML代码混杂在一起的做法同样也非常不妥,因为它并没有将网页内容和行为分离,所以才有JQuery选择器的学习.

点击我

. //给class为demo的元素添加行为.

jquery操作xml

- - CSDN博客Web前端推荐文章
jquery真的很强大,虽然一直在用jquery,不用一直都没有深入,这几天重新学习了一下,不得不感叹她的强大,已经让我深深入迷. 这里记录一下,她是怎么快速地操作xml的.. 这里我们有一个xml文件:. jquery如何操作呢,总的思想,就是和操作dom差不多的方法. 首先我们获取这个文件的内容:(我先引入jquery库哈).

jQuery JSONP跨域

- - Web前端 - ITeye博客
基于Jquery的Ajax跨域访问. 单点登录服务器(sso服务器). 登录网页项目的时候,由于使用了单点登录,所以页面会跳转到sso服务器,进行统一登录,. 现在需要在该界面增加令牌的认证,但是SSO服务器和令牌服务器部署在不同的服务器,且暂时没有要合并的可能,所以在SSO登录的时候必须要对令牌进行验证,就必须涉及到了跨域访问的问题.

jquery 插件

- - JavaScript - Web前端 - ITeye博客
 jQuery插件的开发包括两种:. 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法. jQuery的全局函数就是属于jQuery命名空间的函数,另一种是对象级别的插件开发,即给jQuery对象添加方法. 下面就两种函数的开发做详细的说明. 1 、类级别的插件开发.

让jquery更快

- - JavaScript - Web前端 - ITeye博客
很久没有关注jQuery了,最近重新看了一下,看到一些不错的文章,转来坐一下笔记. 其内容和一些新提供的方法还是很多有值得学习的地方. 使用最新版本的jQuery. jQuery的版本更新很快,你应该总是使用最新的版本. 因为新版本会改进性能,还有很多新功能. 下面就来看看,不同版本的jQuery性能差异有多大.

jQuery Tools:Web开发必备的 jQuery UI 库

- - 博客园_首页
jQuery Tools 是基于. jQuery 开发的网站界面库,包含网站最常用的Tabs(选项卡)、Tooltip(信息提示)、Overlay(遮罩、弹窗)、Scrollable(滚动控制)、Form Validator(表单验证)、Rangeinput(范围选择)、Dateinput(日期选择)等众多功能.