问题

前端小同学在做页面的时候,犯了个常见的错误:把多个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()的返回值

本文转自:https://segmentfault.com/a/1190000008486570

用Promise解决多个异步Ajax请求导致的代码嵌套问题【转】的更多相关文章

  1. Ajax引擎:ajax请求步骤详细代码

    说起AJAX,可能是很多同学在很多地方都看到过,各大招聘网站上对于WEB前端和PHP程序员的技能要求清单中也是必不可少的一项.但是,ajax请求步骤详细代码以及说明却比较少见到 什么是AJAX引擎? ...

  2. 解决拦截器对ajax请求的的拦截

    拦截器配置: public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object obj) ...

  3. 异步ajax请求数据处理

    jQuery.ajax(url,[settings]) 概述 通过 HTTP 请求加载远程数据. jQuery 底层 AJAX 实现.简单易用的高层实现见 $.get, $.post 等.$.ajax ...

  4. 多个异步ajax请求指定顺序执行

    1.比如2个ajax请求,把第二个ajax请求放在第一个ajax请求success方法里面. 2.ajax请求时添加 async: false,//使用同步的方式,true为异步方式.结果是只有等服务 ...

  5. 解决spring-security session超时 Ajax 请求没有重定向的问题

    开始时, 代码是这样的: $.ajax({ type : "POST", url : sSource, cache : false, dataType : "json&q ...

  6. 【django基础】django接口 异步ajax请求 导出数据库成excel表(包裹前端后端)

    py文件: from django.utils.http import urlquote from rest_framework.views import APIView from django.sh ...

  7. springboot+shiro 02 - 异步ajax请求无权限时,返回json格式数据

    博客: https://www.cnblogs.com/youxiu326/p/shiro-01.html github:https://github.com/youxiu326/sb_shiro_s ...

  8. ajax请求, 前后端, 代码示例

    [博客园cnblogs笔者m-yb原创,转载请加本文博客链接,笔者github: https://github.com/mayangbo666,公众号aandb7,QQ群927113708] http ...

  9. ajax请求导致status为canceled(无任何回调数据)的原因

    1.故障现象 一个普通的ajax请求,请求能够到达controller,也能正常处理业务,但是ajax的回调函数为空,即没有任何状态和数据返回,使用谷歌浏览器查看请求状态如下图: 出现该错误:简单来说 ...

随机推荐

  1. Tomcat 服务器安装 SSL证书,实现 HTTP 自动跳转 HTTPS

    本文以阿里云为例: 一.下载证书 1.1.登录阿里云:https://www.aliyun.com/ 1.2.控制台搜索:SSL证书 1.3.进入 SSL证书控制台 1.4.申请免费 SSL证书,已有 ...

  2. Vim——回顾整理

    一.命令练习(一) hjkl(左下上右) 保存到某路径 :saveas 路径 w 到下一个单词的开头 e 到下一个单词的结尾 % 括号匹配移动(),{},[] 0 到行头 $ 到行头 gU字母变大写 ...

  3. IdentityServer4 中文文档 -10- (快速入门)使用密码保护API

    IdentityServer4 中文文档 -10- (快速入门)使用密码保护API 原文:http://docs.identityserver.io/en/release/quickstarts/2_ ...

  4. SQL Server 数据类型映射(转载)

    SQL Server 数据类型映射 SQL Server 和 .NET Framework 基于不同的类型系统. 例如,.NET Framework Decimal 结构的最大小数位数为 28,而 S ...

  5. git+github/码云+VSCode (转载)

    VSCode中使用git,参见. Git安装   在初次使用时如果本地没有安装git会提示先安装git,然后重启vscode. 一.本地操作项目前提: 1)若本地没有git拉取下来的项目,用git克隆 ...

  6. [PHP] 算法-数组中出现次数超过一半的数字的PHP实现

    数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.如果不存在 ...

  7. 深入理解Java虚拟机--阅读笔记三

    垃圾收集器 手机算法是内存回收的方法论,垃圾收集器是内存回收的具体实现. 并行:指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态 并发:值用户线程与垃圾收集线程同时执行(但并不一定是并行的) ...

  8. 垂直水平居中总结css

    水平居中:给div设置一个宽度,然后添加margin:0 auto属性 div{ width:200px; margin:0 auto; } 让绝对定位的div垂直水平居中一(大盒子设置个相对定位) ...

  9. react组件中的constructor和super小知识

    react组件中的constructor和super小知识 1.react中用class申明的类一些小知识 如上图:类Child是通过class关键字申明,并且继承于类React. A.Child的类 ...

  10. 【读书笔记】iOS-iCloud介绍

    iCloud是一种面向消费者市场的云存储服务,苹果公司已经做了大量的工作让用户能够平滑过渡到iCloud,不过对开发者而言这意味着新的负担. 怎样使用iCloud? 你可以使用2种方式在你的应用中使用 ...