概述

在上一篇文章《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. git 设置记住密码和清除密码

    git 设置记住密码和清除密码   1. 永久记住密码 该命令会记住密码,执行一次 git pull 或 git push 等需要输入密码的命令,输入一次密码, 之后就都不必再输入了 git conf ...

  2. Kubernetes网络

    kubernetes-Service 1.service存在的意义 1.防止破的失联(服务发现) 2.定义一组pod的访问策略(提供负载均衡) 2.pod与service的关系 1.通过lablel- ...

  3. Office XXE攻击

    一.什么是Office XXE攻击 Office XXE攻击是xxe攻击的一种,由于.xlsx与.docx是基于xml文件存储内容的,后端在解析这些xml时自然也会存在xxe攻击的可能. 这里是.xl ...

  4. Git文件权限与filemode配置方法

    一.问题 Clion是一个跨平台的IDE,今天将工程运行在Ubuntu下,在Git提交时发现有很多文件显示被更改,但是文件内容却是相同的. 二.Git 规则 Git对文件访问权限的管理与配置选项cor ...

  5. deepin解决文件管理器打不开和桌面黑屏的问题

    总结 deepin 的优点是上手非常容易, 但截止当前(2021-6-24)的使用来说稳定性还不是非常好. 今天就遇到了无法显示桌面的问题,可以参照如下解决办法.只需使用红色框中的命令即可. 图片转载 ...

  6. 背包DP全类型

    AcWing 2. 01背包问题 #include <iostream> #include <algorithm> using namespace std; const int ...

  7. FC 交换机基础配置

    目录 Primera600 存储服务器 FC 交换机 交换机信息查看 交换机配置管理 用户管理 以太网配置 端口配置管理 别名配置 证书管理 角色管理 Zone 管理 参考网址 Primera600 ...

  8. 2023-11-25:用go语言,给定一个数组arr,长度为n,表示n个格子的分数,并且这些格子首尾相连, 孩子不能选相邻的格子,不能回头选,不能选超过一圈, 但是孩子可以决定从任何位置开始选,也可以

    2023-11-25:用go语言,给定一个数组arr,长度为n,表示n个格子的分数,并且这些格子首尾相连, 孩子不能选相邻的格子,不能回头选,不能选超过一圈, 但是孩子可以决定从任何位置开始选,也可以 ...

  9. day01预习-基本语法

    typora-copy-images-to: media 基本语法 JavaScript的历史: ​ 在95年以前,就有很多上网的用户了,当时的带宽只有28.8kb/s,用户要进行表单的验证时,点击提 ...

  10. 月薪3w的报表工程师要会哪些技能?报表工程师的招聘要求解读

    对于月薪3w的报表工程师,通常需要具备以下技能: 1. 数据分析与处理 - 数据仓库:了解数据仓库的设计原则和架构,能够构建和优化数据仓库结构. - SQL语言:熟练掌握SQL查询语言,能够编写复杂的 ...