ES6躬行记(23)——Promise的静态方法和应用
一、静态方法
Promise有四个静态方法,分别是resolve()、reject()、all()和race(),本节将着重分析这几个方法的功能和特点。
1)Promise.resolve()
此方法有一个可选的参数,参数的类型会影响它的返回值,具体可分为三种情况(如下所列),其中有两种情况会创建一个新的已处理的Promise实例,还有一种情况会返回这个参数。
(1)当参数为空或非thenable时,返回一个新的状态为fulfilled的Promise。
(2)当参数为thenable时,返回一个新的Promise,而它的状态由自身的then()方法控制,具体细节已在之前的thenable一节做过说明。
(3)当参数为Promise时,将不做修改,直接返回这个Promise。
下面用一个例子演示这三种情况,注意观察Promise的then()方法的第一个回调函数中接收到的决议结果。
let tha = {
then(resolve, reject) {
resolve("thenable");
}
};
//参数为空
Promise.resolve().then(function(value) {
console.log(value); //undefined
});
//参数为非thenable
Promise.resolve("string").then(function(value) {
console.log(value); //"string"
});
//参数为thenable
Promise.resolve(tha).then(function(value) {
console.log(value); //"thenable"
});
//参数为Promise
Promise.resolve(new Promise(function(resolve) {
resolve("Promise");
})).then(function(value) {
console.log(value); //"Promise"
});
2)Promise.reject()
此方法能接收一个参数,表示拒绝理由,它的返回值是一个新的已拒绝的Promise实例。与Promise.resolve()不同,Promise.reject()中所有类型的参数都会原封不动的传递给后续的已拒绝的回调函数,如下代码所示。
Promise.reject("rejected").catch(function (reason) {
console.log(reason); //"rejected"
});
var p = Promise.resolve();
Promise.reject(p).catch(function (reason) {
reason === p; //true
});
第一次调用Promise.reject()的参数是一个字符串,第二次的参数是一个Promise,catch()方法中的回调函数接收到的正是这两个参数。
3)Promise.all()
此方法和接下来要讲解的Promise.race()都可用来监控多个Promise,当它们的状态发生变化时,这两个方法会给出不同的处理方式。
Promise.all()能接收一个可迭代对象,其中可迭代对象中的成员必须是Promise,如果是字符串、thenable等非Promise的值,那么会自动调用Promise.resolve()转换成Promise。Promise.all()的返回值是一个新的Promise实例,当参数中的成员为空时,其状态为fulfilled;而当参数不为空时,其状态由可迭代对象中的成员决定,具体分为两种情况。
(1)当可迭代对象中的所有成员都是已完成的Promise时,新的Promise的状态为fulfilled。而各个成员的决议结果会组成一个数组,传递给后续的已完成的回调函数,如下所示。
var p1 = Promise.resolve(200),
p2 = "fulfilled";
Promise.all([p1, p2]).then(function (value) {
console.log(value); //[200, "fulfilled"]
});
(2)当可迭代对象中的成员有一个是已拒绝的Promise时,新的Promise的状态为rejected。并且只会处理到这个已拒绝的成员,接下来的成员都会被忽略,其决议结果会传递给后续的已拒绝的回调函数,如下所示。
var p1 = Promise.reject("error"),
p2 = "fulfilled";
Promise.all([p1, p2]).catch(function (reason) {
console.log(reason); //"error"
});
4)Promise.race()
此方法和Promise.all()有很多相似的地方,如下所列。
(1)能接收一个可迭代对象。
(2)成员必须是Promise,对于非Promise的值要用Promise.resolve()做转换。
(3)返回值是一个新的Promise实例。
新的Promise实例的状态也与方法的参数有关,当参数的成员为空时,其状态为pending;当参数不为空时,其状态是最先被处理的成员的状态,并且此成员的决议结果会传递给后续相应的回调函数,如下代码所示。
var p1 = new Promise(function(resolve) {
setTimeout(() => {
resolve("fulfilled");
}, 200);
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(() => {
reject("rejected");
}, 100);
});
Promise.race([p1, p2]).catch(function (reason) {
console.log(reason); //"rejected"
});
在p1和p2的执行器中都有一个定时器。由于后者的定时器会先执行,因此通过调用Promise.race([p1, p2])得到的Promise实例,其状态和p2的相同,而p2的决议结果会作为拒绝理由被catch()方法中的回调函数接收。
根据前面的分析可以得出,Promise.all()能处理一个或多个受监控的Promise,而Promise.race()只能处理其中的一个。
二、应用
1)Promise和生成器
用Promise和生成器实现一个运行器,可以取代冗长的Promise链,以一种更直观的方式控制异步,类似于下面这样。
function load() {
return new Promise(function(resolve, reject) {
resolve("success");
});
}
run(function* () {
var result = yield load();
console.log(result); //"success"
});
在load()函数内部,执行的是异步操作,由于处在run运行器中,因此它的决议结果可通过赋值语句直接给到result。这种工作模式完全颠覆了过去用回调函数接收异步操作结果的模式。为此,ES8规范特地引入了两个关键字:async和await,支持这种便捷的工作模式,下面改写上一个示例,用新语法实现相同的功能。
(async function() {
var result = await load();
console.log(result); //"success"
})();
关于run运行器的工作原理和ES8的新语法,限于篇幅原因,此处不再展开说明。
2)与传统异步操作的组合
以往需要用回调函数接收异步处理结果的操作,现在都能改成Promise的模式。以图像加载为例,当图像载入成功时,会触发load事件;而当失败时,会触发error事件。如果后续又有异步操作,那么就只能在这两个事件中处理,但这么一来,就会形成难以控制的回调金字塔。而改用Promise后,就能链式的处理后续的操作,如下所示。
function preImg(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = src;
img.onload = function(){
resolve(this);
};
img.onerror = function(){
reject(this);
};
});
};
preImg("img/page.png").then(function(value) {
console.log(value);
});
ES6躬行记(23)——Promise的静态方法和应用的更多相关文章
- ES6躬行记(1)——let和const
古语云:“纸上得来终觉浅,绝知此事要躬行”.的确,不管看了多少本书,如果自己不实践,那么就很难领会其中的精髓.自己研读过许多ES6相关的书籍和资料,平时工作中也会用到,但在用到时经常需要上搜索引擎中查 ...
- ES6躬行记 笔记
ES6躬行记(18)--迭代器 要实现以下接口## next() ,return,throw 可以用for-of保证迭代对象的正确性 例如 var str = "向
- ES6躬行记(22)——Promise
在JavaScript中,回调函数是处理异步编程的常用解决方案,但层层嵌套的回调金字塔(如下代码所示)一直受人诟病,因为不仅在视觉上更加混乱,而且在管理上也更为复杂. setTimeout(() =& ...
- ES6躬行记(21)——类的继承
ES6的继承依然是基于原型的继承,但语法更为简洁清晰.通过一个extends关键字,就能描述两个类之间的继承关系(如下代码所示),在此关键字之前的Man是子类(即派生类),而在其之后的People是父 ...
- ES6躬行记(13)——类型化数组
类型化数组(Typed Array)是一种处理二进制数据的特殊数组,它可像C语言那样直接操纵字节,不过得先用ArrayBuffer对象创建数组缓冲区(Array Buffer),再映射到指定格式的视图 ...
- ES6躬行记(5)——对象字面量的扩展
一.简洁属性和方法 当创建对象字面量时,如果属性值是与属性同名的已定义的标识符(例如变量.常量等),那么ES6允许省略冒号和属性值,这样就能避免冗余的初始化.下面分别用传统的键值对和最新的简写方式创建 ...
- ES6躬行记(20)——类
ES6正式将类(Class)的概念在语法层面标准化,今后不必再用构造函数模拟类的行为.而ES6引入的类本质上只是个语法糖(即代码更为简洁.语义更为清晰),其大部分功能(例如继承.封装和复用等)均可在E ...
- ES6躬行记(12)——数组
ES6为数组添加了多个新方法,既对它的功能进行了强化,也消除了容易产生歧义的语法. 一.静态方法 1)of() ES6为Array对象新增的第一个静态方法是of(),用于创建数组,它能接收任意个参数, ...
- ES6躬行记(3)——解构
解构(destructuring)是一种赋值语法,可从数组中提取元素或从对象中提取属性,将其值赋给对应的变量或另一个对象的属性.解构地目的是简化提取数据的过程,增强代码的可读性.有两种解构语法,分别是 ...
随机推荐
- PHP 基础复习 2018-06-21
(1)PHP Zip File 函数 $zip = zip_open("test.zip"); if ($zip) { while ($zip_entry = zip_read($ ...
- python学习之-- IO多路复用 select模块
python I/O多路复用包括3个模块,上一篇已经说过概念,这里我使用的是select模块实现一个ftp并发 服务器端核心代码: import socket,select import queue, ...
- 一致性哈希算法-----> 解决memecache 服务器扩容后的数据丢失。
1 基本场景 比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,你很可能会采用类似下面的通用方法计算 object 的 ...
- asterisk 通道变量
${ACCOUNTCODE}: 用户计费帐号 sip.conf 里的 account=XXXX ${ANSWEREDTIME}: 通话时长(秒) ${BLINDTRANSFER}: 通道是否为转接类型 ...
- Swift初体验之HelloWord+苹果Swift编程语言新手教程【中文版】
AppDelegate.swift : <span style="font-size:24px;"><strong>// // AppDelegate.sw ...
- 电脑控制手机的另一选择——android vnc server
近来发现的Android上的原生VNC Server,就是说只要手机上安装并运行这个软件,即可实现电脑上查看并控制手机了. 首先是手机端. 1)下载androidvncserver: http://c ...
- Linux 下使用 Sar 简介
Linux 下使用 Sar 简介 提交 我的留言 加载中 已留言 介绍 Sar 最早是实现在 Salaris Unix 系统里,后来移植到了大部分其他的 Unix 系统(如AIX,HP-UX等).Li ...
- Citrix XenServer
Citrix XenServer xenserver-test cpu特性码:77fafbff-bfebfbff-00000021-2c100800 xe snapshot-list xen还原快照 ...
- 熊猫猪新系统測试之二:Mac OS X 10.10 优胜美地
在第一篇windows 10技术预览版測试之后.本猫为大家呈现还有一个刚刚才更新的mac操作系统:"优胜美地".苹果相同一改以猫科动物为代号命名的传统.在10.9的Maverick ...
- C语言细节笔记1
/******************************************************************************* ——笔记 1. 函数申明的书写. 可以 ...