一.介绍

是一个容器,里面保存着某个未来才会结束的事件的结果,通常是异步操作。
promise对象有两个特点:

  1. 对象状态不受外界影响
  2. 一旦状态改变,便不会再变

对象的状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
promise是一个构建函数,用来生成promise实例。

  1. const promise = new Promise(function(resolve, reject) {
  2. // ... some code
  3. if (/* 异步操作成功 */){
  4. resolve(value);
  5. } else {
  6. reject(error);
  7. }
  8. });
  9. promise.then(function(value) {
  10. // success
  11. }, function(error) {
  12. // failure
  13. });

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。这两个函数都是可选的,不一定要提供。它们都接受Promise对象传出的值作为参数。

  1. let promise = new Promise(function(resolve, reject) {
  2. console.log('Promise');
  3. resolve();
  4. });
  5. promise.then(function() {
  6. console.log('resolved.');
  7. });
  8. console.log('Hi!');
  9. // Promise
  10. // Hi!
  11. // resolved

上面代码中,Promise 新建后立即执行,所以首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完后才会执行,所以resolved最后输出。
实例:

  1. const getJSON = function(url) {
  2. const promise = new Promise(function(resolve, reject){
  3. const handler = function() {
  4. if (this.readyState !== 4) {
  5. return;
  6. }
  7. if (this.status === 200) {
  8. resolve(this.response);
  9. } else {
  10. reject(new Error(this.statusText));
  11. }
  12. };
  13. const client = new XMLHttpRequest();
  14. client.open("GET", url);
  15. client.onreadystatechange = handler;
  16. client.responseType = "json";
  17. client.setRequestHeader("Accept", "application/json");
  18. client.send();
  19. });
  20. return promise;
  21. };
  22. getJSON("/posts.json").then(function(json) {
  23. console.log('Contents: ' + json);
  24. }, function(error) {
  25. console.error('出错了', error);
  26. });

new完promise,并没有调用它,我们传进去的函数就已经执行了,这是需要注意的一个细节。所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:

  1. function runAsync(){
  2. var p = new Promise(function(resolve, reject){
  3. //做一些异步操作
  4. setTimeout(function(){
  5. console.log('执行完成');
  6. resolve('随便什么数据');
  7. }, 2000);
  8. });
  9. return p;
  10. }
  11. runAsync()

二.then()方法

Promise 实例具有then方法,作用是为 Promise 实例添加状态改变时的回调函数,then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。

三.catch()方法

catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

  1. promise
  2. .then(function(data) { //cb
  3. // success
  4. })
  5. .catch(function(err) {
  6. // error
  7. });

四.finally()

不管 Promise 对象最后状态如何,都会执行的操作.

  1. promise
  2. .then(result => {···})
  3. .catch(error => {···})
  4. .finally(() => {···});

五.Promise.all()

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例.

  1. const p = Promise.all([p1, p2, p3]);

上面代码中,Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。另外,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

  1. // 生成一个Promise对象的数组
  2. const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  3. return getJSON('/post/' + id + ".json");
  4. });
  5. Promise.all(promises).then(function (posts) {
  6. // ...
  7. }).catch(function(reason){
  8. // ...
  9. });

六.Promise.resolve()

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

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

七.Promise.race()

比谁跑得快

  1. //请求某个图片资源
  2. function requestImg(){
  3. var p = new Promise(function(resolve, reject){
  4. var img = new Image();
  5. img.onload = function(){
  6. resolve(img);
  7. }
  8. img.src = 'xxxxxx';
  9. });
  10. return p;
  11. }
  12. //延时函数,用于给请求计时
  13. function timeout(){
  14. var p = new Promise(function(resolve, reject){
  15. setTimeout(function(){
  16. reject('图片请求超时');
  17. }, 5000);
  18. });
  19. return p;
  20. }
  21. Promise
  22. .race([requestImg(), timeout()])
  23. .then(function(results){
  24. console.log(results);
  25. })
  26. .catch(function(reason){
  27. console.log(reason);
  28. });

requestImg函数会异步请求一张图片,我把地址写为”xxxxxx”,所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息

八.应用

  1. const preloadImage = function (path) {
  2. return new Promise(function (resolve, reject) {
  3. const image = new Image();
  4. image.onload = resolve;
  5. image.onerror = reject;
  6. image.src = path;
  7. });
  8. };

https://juejin.cn/post/6844904094079926286