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操作使得该问题变得明显.许多不同的方法都可以解决这个问题,本文讨论了一些方法 ...
随机推荐
- go语言 包依赖管理-构建完整的依赖项目:目录结构及包的调用
目录结构: <home>/ |-- greetings/ |-- hello/1.分别进入对应目录创建以上目录结构 //bash切换到用户主目录 cd $HOMEPAHT$ //bash新 ...
- mac应用已损坏无法打开
sudo xattr -r -d com.apple.quarantine /User/name/yourapp # '/User/name/yourapp' 替换成你自己要安装的 mac 应用地址 ...
- 2020/4/27 日常补坑-tarjan第一道awa
第一题 luoguP1407 我们已知n对夫妻的婚姻状况,称第i对夫妻的男方为Bi,女方为Gi.若某男Bi与某女Gj曾经交往过(无论是大学,高中,亦或是幼儿园阶段,i≠j),则当某方与其配偶(即Bi与 ...
- c# 使用打印机打印并设置打印位置及宽高
1.在界面中使用自带的控件printDocument 2.将以下函数绑定到控件的PrintPage事件 private void printDocument1_PrintPage(object sen ...
- Python 日期和时间处理教程:datetime 模块的使用
Python 中的日期不是独立的数据类型,但我们可以导入一个名为 datetime 的模块来使用日期作为日期对象. 示例:导入 datetime 模块并显示当前日期: import datetime ...
- K8S 组合命令
强制删除namespace kubectl get namespace [namespace-name] -o json | tr -d "\n" | sed "s/\& ...
- video.js 视频
http://www.cnblogs.com/lechenging/p/3858181.html
- QT中级(2)QTableView自定义委托(二)实现QProgressBar委托
同系列文章 QT中级(1)QTableView自定义委托(一)实现QSpinBox.QDoubleSpinBox委托 QT中级(2)QTableView自定义委托(二)实现QProgressBar委托 ...
- TechEmpower 22轮Web框架 性能评测:.NET 8 战绩斐然
自从2022年7月第21轮公布的测试以后,一年后 的2023年10月17日 发布了 TechEmpower 22轮测试报告 刚刚发布:Round 22 results - TechEmpower Fr ...
- 基于C# Socket实现的简单的Redis客户端
前言 Redis是一款强大的高性能键值存储数据库,也是目前NOSQL中最流行比较流行的一款数据库,它在广泛的应用场景中扮演着至关重要的角色,包括但不限于缓存.消息队列.会话存储等.在本文中,我们将介绍 ...