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 相关文章推荐
User Scripts: Video Download by User Scripts
May 14 Javascript
在一个浏览器里呈现所有浏览器测试结果的前端测试工具的思路
Mar 02 Javascript
jquery实现不同大小浏览器使用不同的css样式表的方法
Apr 02 Javascript
JQuery实现带排序功能的权限选择实例
May 18 Javascript
requirejs按需加载angularjs文件实例
Jun 08 Javascript
详解http访问解析流程原理
Oct 18 Javascript
微信小程序简单的canvas裁剪图片功能详解
Jul 12 Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
Sep 23 Javascript
Node.js实现简单管理系统
Sep 23 Javascript
js实现动态时钟
Mar 12 Javascript
JS原型prototype和__proto__用法实例分析
Mar 14 Javascript
node.js +mongdb实现登录功能
Jun 18 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 存储文本换行实现方法
2010/01/05 PHP
ThinkPHP表单自动提交验证实例教程
2014/07/18 PHP
彻底搞懂PHP 变量结构体
2017/10/11 PHP
js定时调用方法成功后并停止调用示例
2014/04/08 Javascript
javascript的数组和常用函数详解
2014/05/09 Javascript
js实现仿百度风云榜可重复多次调用的TAB切换选项卡效果
2015/08/31 Javascript
程序员必知35个jQuery 代码片段
2015/11/05 Javascript
基于jQuery实现点击列表加载更多效果
2016/05/31 Javascript
javascript replace()第二个参数为函数时的参数用法
2016/12/26 Javascript
微信小程序图片选择、上传到服务器、预览(PHP)实现实例
2017/05/11 Javascript
关于meta viewport中target-densitydpi属性详解(推荐)
2017/08/18 Javascript
详解VUE 对element-ui中的ElTableColumn扩展
2018/03/28 Javascript
使用vuepress搭建静态博客的示例代码
2019/02/14 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
微信小程序换肤功能实现代码(思路详解)
2020/08/25 Javascript
JavaScript原生数组函数实例汇总
2020/10/14 Javascript
浅谈MySQL中的触发器
2015/05/05 Python
简析Python的闭包和装饰器
2016/02/26 Python
Python多层嵌套list的递归处理方法(推荐)
2016/06/08 Python
详解Python中表达式i += x与i = i + x是否等价
2017/02/08 Python
解决python中os.listdir()函数读取文件夹下文件的乱序和排序问题
2018/10/17 Python
python实现简单加密解密机制
2019/03/19 Python
Python3.6中Twisted模块安装的问题与解决
2019/04/15 Python
Python从列表推导到zip()函数的5种技巧总结
2019/10/23 Python
Django 项目布局方法(值得推荐)
2020/03/22 Python
删除pycharm鼠标右键快捷键打开项目的操作
2021/01/16 Python
python中random模块详解
2021/03/01 Python
俄罗斯设计师家具购物网站:The Furnish
2019/12/01 全球购物
2014年人民调解工作总结
2014/12/08 职场文书
2014年助理政工师工作总结
2014/12/19 职场文书
颐和园英文导游词
2015/01/30 职场文书
css 中多种边框的实现小窍门
2021/04/07 HTML / CSS
MySQL 十大常用字符串函数详解
2021/06/30 MySQL
Python中基础数据类型 set集合知识点总结
2021/08/02 Python
MySQL数据库实验之 触发器和存储过程
2022/06/21 MySQL
js面向对象编程OOP及函数式编程FP区别
2022/07/07 Javascript