ES6基础之 Promise 对象用法实例详解


Posted in Javascript onAugust 22, 2019

本文实例讲述了ES6基础之 Promise 对象用法。分享给大家供大家参考,具体如下:

Promise 对象

1.Promise对象是ES6对异步编程的一种解决方案,它有以下两个特点:

  • Promise对象代表一个异步操作,它只有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败),并且该状态不会受外界的影响
  • Promise对象的状态改变,只有两种可能:从 Pending 变为 Resolved 或者从 Pending 变为 Rejected,并且一旦状态改变,就不会再变,任何时候都可以得到这个结果

2.Promise对象的一些缺点:

一旦新建了一个Promise对象,就会立即执行,并且无法中途取消

let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
// Promise

如果不设置Promise对象的回调函数,Promise会在内部抛出错误,不会反应到外部,也就是在外部拿不到错误提示

如果Promise对象处于Pending状态时,是无法得知捕获进展到哪一个阶段的(刚刚开始还是即将完成)

3.Promise对象是一个构造函数,用来生成Promise实例,下面是创造了一个Promise实例的示例

let promise = new Promise(function(resolve, reject) {
 // ... to do
 if ( success ){
  resolve(value);  //成功操作
 } else {
  reject(error);   //失败操作
 }
});

ps:Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject ,分别用来处理成功和失败的回调;

4.Promise实例生成以后,可以用 then 方法分别指定 Resolved 状态和 Reject 状态的回调函数;

promise.then(function(value) {
 // success
}, function(error) {
 // failure
});

ps:then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Rejected时调用,其中,第二个函数是可选的;

5.resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作;

let promise1 = new Promise(function (resolve, reject) {
 // ...
});
let promise2 = new Promise(function (resolve, reject) {
 // ...
 resolve(p1);
})

上面代码表示一个异步操作的结果是返回另一个异步操作,promise1 的状态就会传递给 promise2 , 如果 promise1 的状态是Pending,那么 promise2 的回调函数就会等待promise1的状态改变;如果promise1的状态已经是Resolved或者Rejected,那么promise2的回调函数将会立刻执行;

6.Promise实例方法then返回的是一个新的Promise实例,因此可以采用链式写法,即then方法后面再调用另一个then方法

let promise = new Promise(function (resolve, reject) {
 // ...
})
promise.then(function(res) {
  return res.post;
}).then(function(post) {
  // ...
});

ps:上例中依次指定了两个回调函数,第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数,如果返回的是 Promise 对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用

let promise = new Promise(function (resolve, reject) {
 // ...
})
promise.then(function(res) {
  return new Promise(/.../);
}).then(function(res) {
  // Resolved
},function(error){
  // Rejected
});

7.Promise.prototype.catch 方法用于指定发生错误时的回调函数,不仅异步操作抛出错误(即状态就会变为Rejected),而且 then 方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获

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

8.如果Promise状态已经变成Resolved,再抛出错误是无效的

let 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

ps: 出现上述结果是由于 之前提到的 Promise 的状态一旦改变,就永久保持该状态,不会再变了,因此在 resolve 语句后面,再抛出错误,是不会被捕获的

9.Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止,因此建议总是使用catch方法,而不使用then方法的第二个参数,因为使用catch方法可以捕获前面then方法执行中的错误

// bad
promise
 .then(function(data) {
  // success
 }, function(err) {
  // error
 });
// good
promise
 .then(function(data) { //cb
  // success
 })
 .catch(function(err) {
  // error
 });

10.Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例,该方法接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then 方法。

var p1 = new Promise(function (resolve) {
  setTimeout(function () {
    resolve("Hello");
  }, 3000);
});
var p2 = new Promise(function (resolve) {
  setTimeout(function () {
    resolve("World");
  }, 1000);
});
Promise.all([p1, p2]).then(function (result) {
  console.log(result);  // ["Hello", "World"]
});

上面的例子模拟了传输两个数据需要不同的时长,虽然 p2 的速度比 p1 要快,但是 Promise.all 方法会按照数组里面的顺序将结果返回,但 promise 本身并不是一个个的顺序执行的,而是同时开始、并行执行的,可以利用这个特点处理需要多个回调返回后才能进行的操作

11.Promise.race方法和Promise.all方法类似,也接收一个promise对象数组为参数,不同的是只要该数组中的 Promise 对象的状态发生变化(无论是 resolve 还是 reject)该方法都会返回。

var p1 = new Promise(function (resolve) {
setTimeout(function () {
resolve("Hello");
}, 3000);
});
var p2 = new Promise(function (resolve) {
setTimeout(function () {
resolve("World");
}, 1000);
});
Promise.race([p1, p2]).then(function (result) {
console.log(result);  // Wrold
});

12.一般情况下我们都会使用 new Promise() 来创建promise对象,除此之外,可以使用 Promise.resolvePromise.reject这两个方法;

静态方法Promise.resolve(value) 可以认为是 new Promise() 方法的快捷方式

let promise = Promise.resolve('resolved');
//等价于
let promise = new Promise(function(resolve){
resolve('resolved');
});

上述的promise对象立即进入确定(即resolved)状态,并将 'resolved' 传递给后面then里所指定的 onFulfilled 函数。

Promise.resolve('resolved').then(function(value){
console.log(value);
});
// resolved

Promise.reject(error)是和 Promise.resolve(value) 类似的静态方法,是 new Promise() 方法的快捷方式。

let promise = Promise.reject(new Error("出错了"));
//等价于
let promise = new Promise(function(resolve,reject){
reject(new Error("出错了"));
});

上述 promise 对象通过then指定的 onRejected 函数,并将错误(Error)对象传递给这个 onRejected 函数

Promise.reject(new Error("fail!")).catch(function(error){
console.error(error);
});
// Error : fail!

13.我们可以利用 Promise 应用到我们实际开发中,下面举几个栗子

//图片加载
const preloadImage = function (path) {
 return new Promise(function (resolve, reject) {
  var image = new Image();
  image.onload = resolve(image);
  image.onerror = function() {
    reject(new Error('Could not load image at ' + path));
  };
  image.src = path;
 });
}
//文件读取
function reader (file) {
 return new Promise(function (resolve, reject) {
  let reader = new FileReader();
  reader.onload = function () {
   resolve(reader);
  };
  reader.onerror = function() {
    reject(new Error('Could not open the file ' + file));
  };
  if (!file.type || /^text\//i.test(file.type)) {
   reader.readAsText(file);
  } else {
   reader.readAsDataURL(file);
  }
 })
}

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

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

Javascript 相关文章推荐
javascript 页面划词搜索JS
Sep 28 Javascript
JavaScript中常见陷阱小结
Apr 27 Javascript
收集的10个免费的jQuery相册
Feb 26 Javascript
js字符串的各种格式的转换 ToString,Format
Aug 08 Javascript
jQuery学习笔记之jQuery原型属性和方法
Jun 09 Javascript
jQuery实现页面滚动时动态加载内容的方法
Mar 20 Javascript
js控制台输出的方法(详解)
Nov 26 Javascript
基于JS实现9种不同的面包屑和分布式多步骤导航效果
Feb 21 Javascript
JavaScript实现左右下拉框动态增删示例
Mar 09 Javascript
vue音乐播放器插件vue-aplayer的配置及其使用实例详解
Jul 10 Javascript
Vue路由权限控制解析
Nov 09 Javascript
JavaScript实现原型封装轮播图
Dec 27 Javascript
ES6基础之数组和对象的拓展实例详解
Aug 22 #Javascript
node express使用HTML模板的方法示例
Aug 22 #Javascript
vue中使用v-model完成组件间的通信
Aug 22 #Javascript
layui动态表头的实现代码
Aug 22 #Javascript
深入理解令牌认证机制(token)
Aug 22 #Javascript
聊聊鉴权那些事(推荐)
Aug 22 #Javascript
在Node.js中将SVG图像转换为PNG,JPEG,TIFF,WEBP和HEIF格式的方法
Aug 22 #Javascript
You might like
PHP开发文件系统实例讲解
2006/10/09 PHP
浅谈php函数serialize()与unserialize()的使用方法
2014/08/19 PHP
php中http与https跨域共享session的解决方法
2014/12/20 PHP
Discuz!X中SESSION机制实例详解
2015/09/23 PHP
javascript 必知必会之closure
2009/09/21 Javascript
原生js实现半透明遮罩层效果具体代码
2013/06/06 Javascript
关闭浏览器窗口弹出提示框并且可以控制其失效
2014/04/15 Javascript
深入理解JavaScript系列(26):设计模式之构造函数模式详解
2015/03/03 Javascript
JavaScript实现的链表数据结构实例
2015/04/02 Javascript
JS简单判断字符在另一个字符串中出现次数的2种常用方法
2017/04/20 Javascript
jquery实现下拉菜单的手风琴效果
2017/07/23 jQuery
Vue中div contenteditable 的光标定位方法
2018/08/25 Javascript
javascript实现5秒倒计时并跳转功能
2019/06/20 Javascript
Javascript Dom元素获取和添加详解
2019/09/24 Javascript
[01:42:49]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD BO3 第一场 2月26日
2021/03/11 DOTA
python每次处理固定个数的字符的方法总结
2013/01/29 Python
Python中__new__与__init__方法的区别详解
2015/05/04 Python
PyQt5每天必学之切换按钮
2020/08/20 Python
Python使用gRPC传输协议教程
2018/10/16 Python
Python TCP通信客户端服务端代码实例
2019/11/21 Python
python scatter函数用法实例详解
2020/02/11 Python
使用pyplot.matshow()函数添加绘图标题
2020/06/16 Python
python 6行代码制作月历生成器
2020/09/18 Python
python 如何区分return和yield
2020/09/22 Python
详解淘宝H5 sign加密算法
2020/08/25 HTML / CSS
金牌葡萄酒俱乐部:Gold Medal Wine Club
2017/11/02 全球购物
英国异国风情旅游网站:Travel Talk Tours(团体旅游、探险旅游、帆船假期)
2018/07/26 全球购物
英国在线药房:Chemist.co.uk
2019/03/26 全球购物
工商管理本科毕业生求职信范文
2013/10/05 职场文书
三潭印月的导游词
2015/02/12 职场文书
绿里奇迹观后感
2015/06/15 职场文书
酒桌上的祝酒词
2015/08/12 职场文书
Mysql8.0递归查询的简单用法示例
2021/08/04 MySQL
关于JS中的作用域中的问题思考分享
2022/04/06 Javascript
Java GUI编程菜单组件实例详解
2022/04/07 Java/Android
Python  序列化反序列化和异常处理的问题小结
2022/12/24 Python