(84)Wangdao.com第十八天_JavaScript Promise 对象
Promise 对象
是 JavaScript 的异步操作解决方案,为异步操作提供统一接口。
目前 JavaScript 原生支持 Promise 对象
它起到代理作用(proxy),充当异步操作与回调函数之间的中介,使得异步操作具备同步操作的接口。
Promise 可以让异步操作写起来,就像在写同步操作的流程,而不必一层层地嵌套回调函数。
- Promise 是一个对象,也是一个构造函数
function f1(resolve, reject) {
// 异步代码...
} var p1 = new Promise(f1);
//Promise
构造函数接受一个回调函数f1()
作为参数,f1()
里面是异步操作的代码。然后,返回的p1
就是一个 Promise 实例
- Promise 的设计思想是
- 所有异步任务都返回一个 Promise 实例。
- Promise 实例有一个 then 方法,用来指定下一步的回调函数。
var p1 = new Promise(f1);
p1.then(f2);f1() 的异步操作执行完成,就会执行 f2()
- 不仅改善了可读性,而且对于多层嵌套的回调函数尤其方便。
- 传统的写法可能需要把 f2() 作为回调函数传入 f1(),比如写成f1(f2),异步操作完成后,在 f1() 内部调用 f2()。
- 而 Promise 使得 f1() 和 f2() 变成了链式写法。
// 传统写法
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// ...
});
});
});
}); // Promise 的写法
(new Promise(step1)).then(step2).then(step3).then(step4);
- 不仅改善了可读性,而且对于多层嵌套的回调函数尤其方便。
- 通过自身的状态,来控制异步操作。
- Promise 实例具有三种状态:
- 异步操作未完成(pending)
- 异步操作成功(fulfilled)
- 异步操作失败(rejected)
- 上面三种状态里面,fulfilled 和 rejected合在一起称为 resolved(已定型)。
- 这三种的状态的变化途径只有两种:
- 从 “未完成” 到 “成功”
- 从 “未完成” 到 “失败”
- 它的英语意思是“承诺”,一旦承诺成效,就不得再改变了。
- 一旦状态发生变化,就凝固了,不会再有新的状态变化。
- 这也意味着,Promise 实例的状态变化只可能发生一次。
- Promise 构造函数
- JavaScript 提供原生的 Promise 构造函数,用来生成 Promise 实例
var promise = new Promise(function (resolve, reject) {
// ... if (/* 异步操作成功 */){
resolve(value);
} else { /* 异步操作失败 */
reject(new Error());
}
});
// 该函数的两个参数分别是resolve
和reject
。它们是两个函数,由 JavaScript 引擎提供,不用自己实现resolve() 函数
作用是,将Promise实例的状态从“未完成”变为“成功”(即从pending变为fulfilled)
在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
reject函数
作用是,将Promise实例的状态从“未完成”变为“失败”(即从pending变为rejected)
在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
- 实例
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
} timeout(100)上面代码中,timeout(100) 返回一个 Promise 实例。100毫秒以后,该实例的状态会变为 fulfilled
- JavaScript 提供原生的 Promise 构造函数,用来生成 Promise 实例
- Promise.prototype.then()
- Promise 实例的then方法,用来添加回调函数
- 可以接受两个回调函数,一旦状态改变,就调用相应的回调函数。
- 第一个是异步操作成功时(变为fulfilled状态)的回调函数
- 第二个是异步操作失败(变为rejected)时的回调函数(该参数可以省略)。
var p1 = new Promise(function (resolve, reject) {
resolve('成功');
});
p1.then(console.log, console.error); // "成功" var p2 = new Promise(function (resolve, reject) {
reject(new Error('失败'));
});
p2.then(console.log, console.error); // Error: 失败p1 和 p2 都是Promise 实例,它们的 then() 方法绑定两个回调函数:成功时的回调函数 console.log,失败时的回调函数 console.error(可以省略)。
p1 的状态变为成功,p2 的状态变为失败
对应的回调函数会收到异步操作传回的值,然后在控制台输出
- 实例:图片加载
- 使用 Promise 完成图片的加载
var preloadImage = function (path) {
return new Promise(function (resolve, reject) {
var image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};调用
preloadImage('https://example.com/my.jpg')
.then(function (e) { document.body.append(e.target) })
.then(function () { console.log('加载成功') })
- 使用 Promise 完成图片的加载
- 强大之处:
- 让回调函数变成了规范的链式写法,程序流程可以看得很清楚。
- 它有一整套接口,可以实现许多强大的功能,
- 比如同时执行多个异步操作,等到它们的状态都改变以后,再执行一个回调函数
- 再比如,为多个回调函数中抛出的错误,统一指定处理方法等等。
- 它的状态一旦改变,无论何时查询,都能得到这个状态。
- 这意味着,无论何时为 Promise 实例添加回调函数,该函数都能正确执行。
- 所以,你不用担心是否错过了某个事件或信号。
- 如果是传统写法,通过监听事件来执行回调函数,一旦错过了事件,再添加回调函数是不会执行的。
- 微任务(Microtask)
- Promise 的回调函数属于异步任务,会在同步任务之后执行。
new Promise(function (resolve, reject) {
resolve(1);
}).then(console.log); console.log(2);
//
// 1
// 上面代码会先输出 2,再输出 1 。
// 因为 console.log(2)是同步任务,而 then 的回调函数属于异步任务,一定晚于同步任务执行
- Promise 的回调函数不是正常的异步任务,而是微任务(microtask)
- 它们的区别在于
- 正常任务追加到下一轮事件循环
- 微任务追加到本轮事件循环
- 这意味着,微任务的执行时间一定早于正常任务。
setTimeout(function() {
console.log(1);
}, 0); new Promise(function (resolve, reject) {
resolve(2);
}).then(console.log); console.log(3);
//
//
//输出结果是321。这说明 then 的回调函数的执行时间,早于setTimeout(fn, 0)。
因为 then 是本轮事件循环执行,setTimeout(fn, 0)在下一轮事件循环开始时执行
- Promise 的回调函数属于异步任务,会在同步任务之后执行。
(84)Wangdao.com第十八天_JavaScript Promise 对象的更多相关文章
- (84)Wangdao.com第十八天_JavaScript 文档对象模型 DOM
文档对象模型 DOM DOM 是 JavaScript 操作网页的接口, 全称为“文档对象模型”(Document Object Model). 作用是将网页转为一个 JavaScript 对象,从而 ...
- (73)Wangdao.com第十二天_JavaScript consol 对象与控制台
consol 对象 console对象是 JavaScript 的原生对象 它有点像 Unix 系统的标准输出stdout和标准错误stderr, 可以输出各种信息到控制台,并且还提供了很多有用的辅助 ...
- (85)Wangdao.com第十八天_JavaScript NodeList 接口,HTMLCollection 接口
NodeList 接口 HTMLCollection 接口 节点都是单个对象,有时需要一种数据结构,能够容纳多个节点 DOM 提供两种节点集合,用于容纳多个节点:NodeList 和 H ...
- angular学习笔记(二十八-附2)-$http,$resource中的promise对象
下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到: HttpREST.factory('cardResource',function($resource) ...
- ES6深入学习记录(二)promise对象相关
1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件更合理和强大.ES6将其写进了语言标准,统一了用法,原生提供了promise对象. 所谓Promis ...
- es6中的promise对象
Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...
- ES6的promise对象应该这样用
ES6修补了一位Js修真者诸多的遗憾. 曾几何时,我这个小白从js非阻塞特性的坑中爬出来,当我经历了一些回调丑陋的写法和优化的尝试之后,我深深觉得js对于多线程阻塞式的开发语言而言,可能有着其太明显的 ...
- Angularjs promise对象解析
1.先来看一段Demo,看完这个demo你可以思考下如果使用$.ajax如何处理同样的逻辑,使用ng的promise有何优势? var ngApp=angular.module('ngApp',[]) ...
- JavaScript异步编程(1)- ECMAScript 6的Promise对象
JavaScript的Callback机制深入人心.而ECMAScript的世界同样充斥的各种异步操作(异步IO.setTimeout等).异步和Callback的搭载很容易就衍生"回调金字 ...
随机推荐
- Java基础知识拾遗(一)
类型提升规则 Java定义了几个应用于表达式的类型提升规则:所有byte.short和char类型的值都被提升为int类型.如果有一个操作数是long类型,将这个表达式提升为 long 类型:如果有一 ...
- jQuery使用(九):队列及实现原理、基于队列模拟实现animate()
开篇一张图之队列模型 queue()如何使用? queue()原理实现? 基于queue()模拟实现animate() 一.使用queuer方法.理解队列原理 queue() dequeue() cl ...
- 第二节:比较DateTime和DateTimeOffset两种时间类型并介绍Quartz.Net中用到的几类时间形式(定点、四舍五入、倍数、递增)
一. 时间的类型 1. 背景 这里为什么要介绍时间类型呢,明明是定时调度篇,原因是在定时任务中,任务什么时间开始执行,什么时间结束执行,要用到各种各样的时间模式,虽然这不能算是一个复杂的问题,但在正式 ...
- [再寄小读者之数学篇](2014-06-23 Bernstein's inequality)
$$\bex \supp \hat u\subset \sed{2^{j-2}\leq |\xi|\leq 2^j} \ra \cfrac{1}{C}2^{jk}\sen{f}_{L^p} \leq ...
- 在JS中如何判断所输入的是一个数、整数、正数、非数值?
1.判断是否为一个数字: Number(num)不为 NaN,说明为数字 2. 判断一个数为正数: var num=prompt("请输入:"); if(Number(num)&g ...
- Dijkstra算法的C++实现
Dijkstra算法是在图中寻找两顶点最短路径的算法. 下面以下图有向图为例,说明其基本思想. 上图为转化为邻接矩阵存储: 现在我要寻找1点到其他点的最短距离以及路径: a)1点到各点的距 ...
- conda安装cv2库
conda install opencv-python或者 pip install opencv-python(不过好像是这个比较有效)
- Tomcat zabbix监控、jmx监控、zabbix_java_gateway
几种方式监控tomcat,如标题. 下面就是参考的网上的连接.自己可以试一下. 由于牵扯到jvm的很多东西, 在这里就只是粘贴处连接参考. http://www.cnblogs.com/chrisDu ...
- SpringBoot入门基础
目录 SpringBoot入门 (一) HelloWorld. 2 一 什么是springboot 1 二 入门实例... 1 SpringBoot入门 (二) 属性文件读取... 16 一 自定义属 ...
- C# 微信开发-----微信会员卡(三)激活会员卡
在会员领取了会员卡之后需要做 一个跳转性激活,模式请看下图: 在创建会员卡的时候需要配置下这个参数的值: memberActivate.aspx页面代码如下: <%@ Page Language ...