概述

在上一篇文章《JavaScript异步编程2——结合XMLHttpRequest使用Promise》中,简要介绍了Ajax与Promise的结合使用。这样,我们就有了两个异步操作的例子:读取一个json文件;通过一个地址加载图像。考虑一下,如果存在两个异步操作,它们需要在执行一个操作之后再执行另外一个操作(例如在这里,我们把图像地址存储在json文件中,通过访问json中的地址来加载图像),该如何做呢?

详论

1️⃣回调地狱

为了实现上面说到的功能,假如我们不使用Promise,直接使用回调函数当然也可以实现:

$(function () {
var url = "./1.json"; var req = new XMLHttpRequest();
req.open('GET', url); req.onload = function () {
if (req.status == 200) {
var imgJson = JSON.parse(req.response); var img = new Image();
img.onload = function () {
$(img).appendTo($('#container'));
}; img.onerror = function () {
throw new Error("Load Image Error!");
} img.src = imgJson[0];
} else {
throw new Error(req.statusText);
}
}; req.onerror = function () {
throw new Error("Network Error");
}; req.send();
});

可以看到这里我们使用了两层的嵌套回调,加载图像的异步操作在XMLHttpRequest访问请求的响应回调中实现,这样可以让访问json请求结束了之后立刻去访问图像操作。那么更进一步来假设,需要加入一个行为,在加载图像完成之后再进行操作呢(例如进行图像处理)?这样的话我们就得再加一层回调函数的嵌套。这样,程序由上至下,由前往后的顺序就会变成由外而内——最直观的不便就是,"{}"层级变得多了,程序会变得难以阅读——而这,就是所谓的“回调地狱”了。

2️⃣Promise实现

为了解决“回调地狱”的问题,Promise应运而生。在之前的文章中说过,Promise的目的,是希望异步行为能像同步操作一样遵循顺序,从而避免嵌套回调。也就是说,只要在每次的成功实现,也就是then()方法中,再次返回新的Promise对象,就可以再次调用该Promise对象的then()方法,这样异步行为也就可以像同步操作那样,按顺序组合起来了。并且这个组合是链式的,从前到后的,从而避免了多层嵌套:

$(function () {
function get(url) {
return new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url); req.onload = function () {
//即使是404也会进入这个相应函数,所以需要检测状态
if (req.status == 200) {
//完成许诺,返回响应文本
resolve(req.response);
} else {
//完成未完成,返回错误
reject(Error(req.statusText));
}
}; // 发生错误时的相应函数
req.onerror = function () {
reject(Error("Network Error"));
}; // 发送请求
req.send();
});
} function getImg(uri){
return new Promise(function(resolve, reject){
var img = new Image();
img.onload = function () {
resolve(img);
};
img.onerror = function () {
reject(Error("Load Image Error!"));
}
img.src = uri;
});
} var addressUri = "./1.json";
get(addressUri).then(function (response) {
var imgJson = JSON.parse(response);
return getImg(imgJson[0]);
}, function (error) {
console.error("Failed!", error);
}).then(function(img){
$(img).appendTo($('#container'));
}, function(error){
console.error("Failed!", error);
});
});

参考

  1. JavaScript Promises: An introduction

JavaScript异步编程3——Promise的链式使用的更多相关文章

  1. javascript异步编程,promise概念

    javascript 异步编程 概述 采用单线程模式工作的原因: 避免多线dom操作同步问题,javascript的执行环境中负责执行代码的线程只有一个 内容概要 同步模式和异步模式 事件循环和消息队 ...

  2. Javascript异步编程之三Promise: 像堆积木一样组织你的异步流程

    这篇有点长,不过干货挺多,既分析promise的原理,也包含一些最佳实践,亮点在最后:) 还记得上一节讲回调函数的时候,第一件事就提到了异步函数不能用return返回值,其原因就是在return语句执 ...

  3. JavaScript异步编程的Promise模式(转)

    异步模式在web编程中变得越来越重要,对于web主流语言Javascript来说,这种模式实现起来不是很利索,为此,许多Javascript库(比如 jQuery和Dojo)添加了一种称为promis ...

  4. JavaScript异步编程的Promise模式

    参考: http://www.infoq.com/cn/news/2011/09/js-promise http://www.cnblogs.com/rubylouvre/p/3495286.html ...

  5. JavaScript异步编程(2)- 先驱者:jsDeferred

    JavaScript当前有众多实现异步编程的方式,最为耀眼的就是ECMAScript 6规范中的Promise对象,它来自于CommonJS小组的努力:Promise/A+规范. 研究javascri ...

  6. Promises与Javascript异步编程

    Promises与Javascript异步编程 转载:http://www.zawaliang.com/2013/08/399.html 在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这 ...

  7. 转: Promises与Javascript异步编程

    在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这些年浏览器技术.HTML5以及CSS3等的发展,越来越多的富Web应用出现:在给与我们良好体验的同时,Web开发人员在背后需要处理越来越多 ...

  8. 深入解析Javascript异步编程

    这里深入探讨下Javascript的异步编程技术.(P.S. 本文较长,请准备好瓜子可乐 :D) 一. Javascript异步编程简介 至少在语言级别上,Javascript是单线程的,因此异步编程 ...

  9. JavaScript 异步编程的前世今生(上)

    前言 提到 JavaScript 异步编程,很多小伙伴都很迷茫,本人花费大约一周的业余时间来对 JS 异步做一个完整的总结,和各位同学共勉共进步! 目录 part1 基础部分 什么是异步 part2 ...

  10. 探索Javascript异步编程

    异步编程带来的问题在客户端Javascript中并不明显,但随着服务器端Javascript越来越广的被使用,大量的异步IO操作使得该问题变得明显.许多不同的方法都可以解决这个问题,本文讨论了一些方法 ...

随机推荐

  1. 客制开发tiptop程序随记-pta表结构问题-误删表的恢复

    添加字段的语法:alter table tablename add (column datatype [default value][null/not null],-.); 删除字段的语法:alter ...

  2. daffodil

    import java.util.ArrayList; public class Daffodil { /** * 打印出100-999之间所有的"水仙花数",所谓"水仙 ...

  3. 单元测验4:人格知识大比武2mooc

    单元测验4:人格知识大比武2 返回 本次得分为:10.00/10.00, 本次测试的提交时间为:2020-09-06, 如果你认为本次测试成绩不理想,你可以选择 再做一次 . 1 单选(2分) 关于M ...

  4. MySQL误删恢复方法2

    实际工作中总会发生数据误删除的场景,在没有备份情况下,如何快速恢复误删数据就显得非常重要. 本文基于MySQL的binlog日志机制,当日志格式设置为"binlog_format=ROW&q ...

  5. 虹科分享|虹科Redis企业版数据库带你跑赢MySQL数字时代!

    数字革命悄然爆发,数据库也将成为率先破局的关键技术! 借着互联网爆发的东风,前几年MySQL以其过硬的产品能力及开源优势,一度成为全球最受欢迎的关系型数据库.然而,革命的漫长之路才刚开始,MySQL是 ...

  6. 读写分离-mycat

    读写分离-mycat: 安装mycat: http://dl.mycat.io/1.6.7.1/Mycat-server-1.6.7.1-release-20190627191042-linux.ta ...

  7. docker 仓库-Harbor

    docker 仓库之分布式 Harbor: Harbor 是一个用于存储和分发docker镜像的企业级Registry服务器,由于Vmware 开源,其通过添加一些企业必须的功能特性,例如安全.标识和 ...

  8. MongoDB 中的锁分析

    MongoDB 中的锁 前言 MongoDB 中锁的类型 锁的让渡释放 常见操作使用的锁类型 如果定位 MongoDB 中锁操作 1.查询运行超过20S 的请求 2.批量删除请求大于 20s 的请求 ...

  9. keycloak~为keycloak-services项目添加第三方模块(首创)

    我们在对keycloak框架中的核心项目keycloak-services进行二次开发过程中,发现了一个问题,当时有这种需求,在keycloak-services中需要使用infinispan缓存,我 ...

  10. Terraform 系列-使用Dynamic Blocks对Blocks进行迭代

    系列文章 Terraform 系列文章 Grafana 系列文章 概述 Terraform 系列文章 介绍了使用 Grafana Terraform Provider, 基于 Terraform 的 ...