JavaScript异步编程3——Promise的链式使用
概述
在上一篇文章《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);
});
});
参考
JavaScript异步编程3——Promise的链式使用的更多相关文章
- javascript异步编程,promise概念
javascript 异步编程 概述 采用单线程模式工作的原因: 避免多线dom操作同步问题,javascript的执行环境中负责执行代码的线程只有一个 内容概要 同步模式和异步模式 事件循环和消息队 ...
- Javascript异步编程之三Promise: 像堆积木一样组织你的异步流程
这篇有点长,不过干货挺多,既分析promise的原理,也包含一些最佳实践,亮点在最后:) 还记得上一节讲回调函数的时候,第一件事就提到了异步函数不能用return返回值,其原因就是在return语句执 ...
- JavaScript异步编程的Promise模式(转)
异步模式在web编程中变得越来越重要,对于web主流语言Javascript来说,这种模式实现起来不是很利索,为此,许多Javascript库(比如 jQuery和Dojo)添加了一种称为promis ...
- JavaScript异步编程的Promise模式
参考: http://www.infoq.com/cn/news/2011/09/js-promise http://www.cnblogs.com/rubylouvre/p/3495286.html ...
- JavaScript异步编程(2)- 先驱者:jsDeferred
JavaScript当前有众多实现异步编程的方式,最为耀眼的就是ECMAScript 6规范中的Promise对象,它来自于CommonJS小组的努力:Promise/A+规范. 研究javascri ...
- Promises与Javascript异步编程
Promises与Javascript异步编程 转载:http://www.zawaliang.com/2013/08/399.html 在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这 ...
- 转: Promises与Javascript异步编程
在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这些年浏览器技术.HTML5以及CSS3等的发展,越来越多的富Web应用出现:在给与我们良好体验的同时,Web开发人员在背后需要处理越来越多 ...
- 深入解析Javascript异步编程
这里深入探讨下Javascript的异步编程技术.(P.S. 本文较长,请准备好瓜子可乐 :D) 一. Javascript异步编程简介 至少在语言级别上,Javascript是单线程的,因此异步编程 ...
- JavaScript 异步编程的前世今生(上)
前言 提到 JavaScript 异步编程,很多小伙伴都很迷茫,本人花费大约一周的业余时间来对 JS 异步做一个完整的总结,和各位同学共勉共进步! 目录 part1 基础部分 什么是异步 part2 ...
- 探索Javascript异步编程
异步编程带来的问题在客户端Javascript中并不明显,但随着服务器端Javascript越来越广的被使用,大量的异步IO操作使得该问题变得明显.许多不同的方法都可以解决这个问题,本文讨论了一些方法 ...
随机推荐
- install_failed_uid_changed no root 没有root手机
主页 问题 Installation error: INSTALL_FAILED_UID_CHANGED no root Installation error: INSTALL_FAILED_UID_ ...
- Groovy初学者指南
本文已收录至GitHub,推荐阅读 Java随想录 微信公众号:Java随想录 原创不易,注重版权.转载请注明原作者和原文链接 目录 Groovy & Java Groovy语法 动态类型 元 ...
- 手撕Vue-数据驱动界面改变下
经过上一篇的介绍,数据驱动界面改变 v-model 的双向绑定已告一段落, 剩余的就以这篇文章来完成. 首先完成我们的 v-html,v-text, 其实很简单,就是将我们之前的 v-model 创建 ...
- Go包介绍与初始化:搞清Go程序的执行次序
Go包介绍与初始化:搞清Go程序的执行次序 目录 Go包介绍与初始化:搞清Go程序的执行次序 一.main.main 函数:Go 应用的入口函数 1.1 main.main 函数 1.2 main.m ...
- Chromium 消息循环和线程池详解
Chromium 中的多线程机制由 base 库提供,要理解 Chromium 中的多线程机制,首先要理解的概念就是 base::MessageLoop 和 base::TaskScheduler , ...
- 程序是如何在计算机上被执行的?(下篇:cpu工作原理)
本文接上文程序是如何在计算机上被执行的?(上篇:软件部分),主要内容是机器语言如何在计算机硬件上运行,关于逻辑门,加法器,布尔运算,亦即,cpu的工作原理. 1.逻辑门 以下图片是<三体> ...
- HanLP — Aho-Corasick DoubleArrayTire 算法 ACDAT - 基于双数组字典树的AC自动机
双数组字典树能在O(1)(1是模式串长度)时间内高速完成单串匹配,并且内存消耗可控,然而软肋在于多模式匹配.如果要匹配多个模式串,必须先实现前缀查询,然后频繁截取文本后缀才可多匹配.比如 ushers ...
- FPGA与Simulink联合仿真环境搭建(硬件在环)
硬件在环(HIL) \(\quad\)官方的一些定义:硬件在环 (HIL) 测试是一种实时仿真,让您无需使用系统硬件即可开始测试嵌入式代码.如果正在开发的代码未按照规范运行,您可以通过此项测试来发现可 ...
- 【公告】luogu blog (daiyulong20120222) 即将迁移!
\[\huge\text{luogu blog (daiyulong20120222) 即将迁移到 cnblogs!}\\ \] \[\huge\color{blue}\text{https://ww ...
- Bash—source命令&export命令&bashrc文件
当不使用 source 命令执行脚本时,会创建一个子 shell,在该子 shell 中执行完脚本后退出子 shell.不是用 export 定义的变量只对该 shell 有效,对子 shell 是无 ...