博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用Promise解决多个异步Ajax请求导致的代码嵌套问题
阅读量:5834 次
发布时间:2019-06-18

本文共 4193 字,大约阅读时间需要 13 分钟。

问题

前端小同学在做页面的时候,犯了个常见的错误:把多个Ajax请求顺序着写下来了,而后面的请求,对前面请求的返回结果,是有依赖的。如下面的代码所示:

var someData;$.ajax({            url: '/prefix/entity1/action1',            type: 'GET' ,            async: true,            contentType: "application/json",            success: function (resp) {                //do something on response               someData.attr1 = resp.attr1;            },            error: function (XMLHttpRequest, textStatus, errorThrown) {                //在这个页面里,所有的请求的错误都做同样的处理                if (XMLHttpRequest.status == "401") {                    window.location.href = '/login.html';                } else {                    alert(XMLHttpRequest.responseText);                }            }        });$.ajax({            url: '/prefix/entity2/action2',            type: 'POST' ,            dataType: "json",            data: JSON.stringify(someData),            async: true,            contentType: "application/json",            success: function (resp) {                //do something on response             },            error: function (XMLHttpRequest, textStatus, errorThrown) {                //在这个页面里,所有的请求的错误都做同样的处理                if (XMLHttpRequest.status == "401") {                    window.location.href = '/login.html';                } else {                    alert(XMLHttpRequest.responseText);                }            }        });

以上代码有两个问题:

*首先就是执行顺序不能保证,action2很可能在action1返回之前就发出了,导致someData.attr1这个参数没能正确传出
*其次两个ajax请求的代码重复很严重

思路

  • 代码重复的问题相对好解决,尤其是在自己的项目里,各种参数可以通过规范定死,封装一个参数更少的ajax方法就好了

//url:地址//data:数据对象,在函数内部会转化成json串,如果没传,表示用GET方法,如果传了,表示用POST方法function ajax(url, data, callback) {        $.ajax({            url: url,            type: data == null ? 'GET' : 'POST',            dataType: "json",            data: data == null ? '' : JSON.stringify(data),            async: true,            contentType: "application/json",            success: function (resp) {                callback(resp);            },            error: function (XMLHttpRequest, textStatus, errorThrown) {                if (XMLHttpRequest.status == "401") {                    window.parent.location = '/enterprise/enterprise_login.html';                    self.location = '/enterprise/enterprise_login.html';                } else {                    alert(XMLHttpRequest.responseText);                }            }        });}

这样只有url,data和callback三个必要的参数要填,其他都定死了

  • 执行顺序的问题,可以把第二个请求放在第一个请求的回调里,形如:

ajax('/prefix/entity1/action1',null, function(resp){     //do something on response     someData.attr1 = resp.attr1;     ajax('/prefix/entity2/action2', someData, function(resp){          //do something on response     }};

至此问题似乎解决得很完美,但可以想见,如果请求不止两个,而是4、5个,同时还有其他异步操作(比如我们的页面里有Vue对象的初始化),相互之间有依赖关系,光是这样层层叠叠的括号嵌套,就已经让人头晕了。

需要找到一种方法,让异步调用的表达看起来像同步调用一样。

正好最近看了阮一峰老师关于ES6的书,而且用户也没有强硬要求兼容IE浏览器,于是就选择了Promise的方案

解决方案

  • 引入Promise

    其实现代浏览器都已经内置支持了Promise,连第三方库都不需要了,只有IE不行,放弃了

  • 改造ajax封装函数,在成功的时候调用resolve(),失败的时候调用reject(),并且返回Promise对象

function ajax(url, data, callback) {    var p = new Promise(function (resolve, reject) {        $.ajax({            url: url,            type: data == null ? 'GET' : 'POST',            dataType: "json",            data: data == null ? '' : JSON.stringify(data),            async: true,            contentType: "application/json",            success: function (resp) {                callback(resp);                resolve();            },            error: function (XMLHttpRequest, textStatus, errorThrown) {                if (XMLHttpRequest.status == "401") {                    window.parent.location = '/enterprise/enterprise_login.html';                    self.location = '/enterprise/enterprise_login.html';                } else {                    alert(XMLHttpRequest.responseText);                }                reject();            }        });    });    return p;}
  • 修改调用端

ajax('/prefix/entity1/action1',null, function(resp){     //do something on response     someData.attr1 = resp.attr1;}).then(     ajax('/prefix/entity2/action2', someData, function(resp){          //do something on response     }).then(     initVue() ;).then(     //do  something else)

至此完美解决。


经@miroki 提醒,发现Jquery从1.5版开始,返回的就是thenable对象了,那么ajax函数可以直接返回$.ajax()的返回值

转载地址:http://yfycx.baihongyu.com/

你可能感兴趣的文章
31载春运 老铁警退休前站好最后一班岗
查看>>
南京少年交警帅气“开拔”
查看>>
特雷莎·梅严防议会架空 不排除延后英国“脱欧”
查看>>
陕西咸阳发掘秦墓75座 发现中西交流特色琉璃珠
查看>>
高雄购房调查:本地与外地人都看好三块区域
查看>>
中国环境损害司法鉴定机构突破100家
查看>>
首创置业“中国之家-和园”将在巴黎开工奠基
查看>>
NoSQL还是SQL?这一篇讲清楚
查看>>
建议收藏:你想要的开发和设计资源全部都在这里
查看>>
基于 D3.js 绘制动态进度条
查看>>
你为什么会被解雇? — Top 10 面试问题解析
查看>>
lodash源码分析之缓存使用方式的进一步封装
查看>>
Android复杂数据流的“高效”渲染(二)
查看>>
Android监测用户行为之中AOP编程之AspectJ实战
查看>>
用 Swift 来刷 leet code 吧 (1-20)
查看>>
20分钟上手 webAssembly
查看>>
SpringBoot下使用定时任务的方式全揭秘
查看>>
强引用、弱引用、软引用
查看>>
Maven构建自动化
查看>>
刷前端面经笔记(四)
查看>>