ES6新特性六:promise对象实例详解


Posted in Javascript onApril 21, 2017

本文实例讲述了ES6新特性之promise对象。分享给大家供大家参考,具体如下:

1. promise 介绍

它是一个对象,也就是说与其他JavaScript对象的用法,没有什么两样;其次,它起到代理作用(proxy),充当异步操作与回调函数之间的中介。它使得异步操作具备同步操作的接口,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套。

它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程。这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。

异步操作f1返回一个Promise对象,它的回调函数f2写法如下

(new Promise(f1)).then(f2);

2. promise 对象的三种状态

① 异步操作未完成(pending)
② 异步操作已完成(resolved)
③ 异步操作失败(rejected)

3. 工作过程

Promise对象使用then方法添加回调函数。then方法可以接受两个回调函数,第一个是异步操作成功时(变为resolved状态)时的回调函数,第二个是异步操作失败(变为rejected)时的回调函数(可以省略)。一旦状态改变,就调用相应的回调函数,这两个回调函数都接受异步操作传回的值作为参数

promise.then(
 console.log,
 console.error
);

4. then 的链式使用

① 首先then方法返回的一个新的promise对象,因此可以采用链式写法。

② then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。

③ 如下,promise的状态一旦变为resolved,就依次调用后面每一个then指定的回调函数,每一步都必须等到前一步完成,才会执行。最后一个then方法的回调函数console.log和console.error,用法上有一点重要的区别。console.log只显示回调函数step3的返回值,console.error可以显示step1、step2、step3之中任意一个发生的错误,Promises对象的错误有传递性。

promise
 .then(step1)
 .then(step2)
 .then(step3)
 .then(
  console.log,
  console.error
 );

5. promise 对象的使用

var promise = new Promise(function(resolve, reject) { // promise的构造函数,Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject
 // 异步操作的代码
 if (/* 异步操作成功 */){
  resolve(value);//将异步的操作结果作为参数传递出去
 } else {
  reject(error);
 }
});

其中resolve和reject它们是两个函数,由JavaScript引擎提供,不用自己部署。

resolve函数的作用:将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject函数的作用:将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

① 下面是一个用Promise对象实现的Ajax操作的例子

var getJSON = function(url) {
 var promise = new Promise(function(resolve, reject){
  var client = new XMLHttpRequest();
  client.open("GET", url);
  client.onreadystatechange = handler;
  client.responseType = "json";
  client.setRequestHeader("Accept", "application/json");
  client.send();
  function handler() {
   if (this.readyState !== 4) {
    return;
   }
   if (this.status === 200) {
    resolve(this.response);//会将参数传递给回调函数
   } else {
    reject(new Error(this.statusText));
   }
  };
 });
 return promise;
};
getJSON("/posts.json").then(function(json) {
 console.log('Contents: ' + json);
}, function(error) {
 console.error('出错了', error);
});

② resolve函数的参数除了正常的值以外,还可能是另一个Promise实例,即一个异步操作的结果是返回另一个异步操作。

var p1 = new Promise(function (resolve, reject) {
 // ...
});
var p2 = new Promise(function (resolve, reject) {
 // ...
 resolve(p1);
})

6.Promise.prototype.catch()

① 一个 Promise 对象,如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误。

promise.then(function(posts) {
 // ...
}).catch(function(error) {
 // 处理 getJSON 和 前一个回调函数运行时发生的错误
 console.log('发生错误!', error);
});

② 另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。

var promise = new Promise(function(resolve, reject) {
 throw new Error('test');
});
promise.catch(function(error) {
 console.log(error);
});
// Error: test

③ 另外两种写法

// 写法一
var promise = new Promise(function(resolve, reject) {
 try {
  throw new Error('test');
 } catch(e) {
  reject(e);
 }
});
promise.catch(function(error) {
 console.log(error);
});
// 写法二
var promise = new Promise(function(resolve, reject) {
 reject(new Error('test'));//reject方法的作用,等同于抛出错误
});
promise.catch(function(error) {
 console.log(error);
});

④ Promise 在resolve语句后面再抛出错误不会被捕获。因为 Promise 的状态一旦改变,就永久保持该状态,不会再变了。

var promise = new Promise(function(resolve, reject) {
 resolve('ok');
 throw new Error('test');
});
promise
 .then(function(value) { console.log(value) })
 .catch(function(error) { console.log(error) });
// ok

7 Promise.all()

参数为Promise 对象的数组;将多个Promisre 对象包装成一个新的Promise 对象,如果数组中不是Promise 对象,就会自动调用 Promise.resolve方法,将参数转为Promise实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例)

var p = Promise.all(promises).then(function (posts) {
 // ...
}).catch(function(reason){
 // ...
});

① 只要promises之中有一个状态变为rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
② 如果全部都变为resolved;此时 promises 数组中所有对象的返回值组成一个数组,传递给p的回调函数。

8 Promise.resolve()

将现有对象转为 Promise对象,Promise.resolve方法就起到这个作用。

Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))

① 参数为Priomise 对象,Promise.resolve() 不做任何处理。
② 参数是一个具有 then 方法的对象:Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thenable对象的then方法。

let thenable = {
 then: function(resolve, reject) {
  resolve(42);
 }
};
let p1 = Promise.resolve(thenable);//p1为一个状态已经是resolved 的promise对象.
p1.then(function(value) {
 console.log(value); // 42
});

③ 参数不是具有then方法的对象,或根本就不是对象

该参数变为生成的 Promise 对象的 resolve() 的参数。

var p = Promise.resolve('Hello');//Hello 会传递给 p 的resolve()
p.then(function (s){
 console.log(s)
});
// Hello

希望本文所述对大家ECMAScript程序设计有所帮助。

Javascript 相关文章推荐
javascript给span标签赋值的方法
Nov 26 Javascript
浏览器检测JS代码(兼容目前各大主流浏览器)
Feb 21 Javascript
jquery判断对象是否为空并遍历对象的简单实例
Jul 26 Javascript
浅谈React 属性和状态的一些总结
Nov 21 Javascript
JavaScript之underscore_动力节点Java学院整理
Jul 03 Javascript
vue-ajax小封装实例
Sep 18 Javascript
js限制input只能输入有效的数字(第一个不能是小数点)
Sep 28 Javascript
解决在layer.open中使用时间控件laydate失败的问题
Sep 11 Javascript
Js参数RSA加密传输之jsencrypt.js的使用
Feb 07 Javascript
javascript canvas封装动态时钟
Sep 30 Javascript
antd Select下拉菜单动态添加option里的内容操作
Nov 02 Javascript
多种类型jQuery网页验证码插件代码实例
Jan 09 jQuery
ES6新特性五:Set与Map的数据结构实例分析
Apr 21 #Javascript
webpack配置的最佳实践分享
Apr 21 #Javascript
详解Vue.js 2.0 如何使用axios
Apr 21 #Javascript
ES6新特性四:变量的解构赋值实例
Apr 21 #Javascript
jQuery+pjax简单示例汇总
Apr 21 #jQuery
利用n工具轻松管理Node.js的版本
Apr 21 #Javascript
基于jQuery实现文字打印动态效果
Apr 21 #jQuery
You might like
PHP中文分词的简单实现代码分享
2011/07/17 PHP
对于PHP 5.4 你必须要知道的
2013/08/07 PHP
php多进程模拟并发事务产生的问题小结
2018/12/07 PHP
php数组和链表的区别总结
2019/09/20 PHP
再次更新!MSClass (Class Of Marquee Scroll通用不间断滚动JS封装类 Ver 1.6)
2007/02/05 Javascript
什么是 AngularJS?AngularJS简介
2014/12/06 Javascript
jquery实现横向图片轮播特效代码分享
2015/11/19 Javascript
解决JavaScript数字精度丢失问题的方法
2015/12/03 Javascript
基于jQuery实现Ajax验证用户名是否存在实例
2016/03/30 Javascript
点击按钮出现60秒倒计时的简单js代码(推荐)
2016/06/07 Javascript
bootstarp modal框居中显示的实现代码
2017/02/18 Javascript
jQuery插件FusionCharts绘制的2D帕累托图效果示例【附demo源码】
2017/03/28 jQuery
Node.js中看JavaScript的引用
2017/04/22 Javascript
详解AngularJS1.6版本中ui-router路由中/#!/的解决方法
2017/05/22 Javascript
vue.js实现备忘录功能的方法
2017/07/10 Javascript
three.js加载obj模型的实例代码
2017/11/10 Javascript
利用babel将es6语法转es5的简单示例
2017/12/01 Javascript
async/await地狱该如何避免详解
2018/05/10 Javascript
jQuery实现飞机大战小游戏
2020/07/05 jQuery
openlayers 3实现车辆轨迹回放
2020/09/24 Javascript
python3学习笔记之多进程分布式小例子
2018/02/13 Python
python协程gevent案例 爬取斗鱼图片过程解析
2019/08/27 Python
Python的互斥锁与信号量详解
2019/09/12 Python
python2和python3应该学哪个(python3.6与python3.7的选择)
2019/10/01 Python
Python函数默认参数常见问题及解决方案
2020/03/26 Python
python Protobuf定义消息类型知识点讲解
2021/03/02 Python
澳大利亚足球鞋和服装购物网站:Ultra Football
2018/10/11 全球购物
医药工作者的求职信范文
2013/09/21 职场文书
单位单身证明样本
2014/10/11 职场文书
2015公务员试用期工作总结
2014/12/12 职场文书
奖学金感谢信
2015/01/21 职场文书
2015年法制宣传月活动总结
2015/03/26 职场文书
2016年秋季运动会广播稿
2015/12/21 职场文书
《攀登者》:“海拔8000米以上,你不能指望任何人”
2019/11/25 职场文书
vue中data里面的数据相互使用方式
2022/06/05 Vue.js
mysql sock文件存储了什么信息
2022/07/15 MySQL