你不知道的 Promise

1.Promise的resolve参数

1.1 普通的值或者对象

resolve方法的参数是普通值或对象时,Promise状态是直接改变的。

new Promise((resolve, reject) => {
  // pending -> fulfilled
  // resolve(基本数据类型或普通对象)
  resolve('promise');
  // resolve({name: 'fct'});
}).then(res => {
  console.log("res:", res);// res 即为 promise
}, err => {
  console.log("err:", err);
})

1.2 传入一个Promise

那么当前的Promise的状态会由传入的参数Promise来决定,相当于状态改变权进行了移交。

const newPromise = new Promise((resolve, reject) => {
  // resolve("aaaaaa")
  reject("err message")
})

new Promise((resolve, reject) => {
  // pending -> fulfilled
  resolve(newPromise);	// 状态由 newPromise决定
}).then(res => {
  console.log("res:", res);
}, err => {
  console.log("err:", err);// err 为err message
})

1.3 传入一个有then方法的对象

会执行该then方法, 并且由该then方法决定后续Promise状态。

new Promise((resolve, reject) => {
  // pending -> fulfilled
  const obj = {
    then: function(resolve, reject) {
      // resolve("resolve message");
      reject("reject message");
    }
  }
  resolve(obj)
}).then(res => {
  console.log("res:", res);
}, err => {
  console.log("err:", err);// err 为 reject message
})

2. Promise的then方法

then方法本身也是有返回值的, 它的返回值是Promise,因此可以链式调用。

传入then方法的回调函数,默认是返回 undefined

2.1 then方法可以多次调用

同一个Promise可以多次调用then方法,当我们的resolve方法被回调时, 所有的then方法传入的回调函数都会被调用。

const promise = new Promise((resolve, reject) => {
  resolve("hahaha")
})

promise.then(res => {
  console.log("res1:", res)	// 输出:'res1: hahaha'
})

promise.then(res => {
  console.log("res2:", res)	// 输出:'res2: hahaha'
})

promise.then(res => {
  console.log("res3:", res)	// 输出:'res3: hahaha'
})

2.2 传入then 方法的回调函数的不同返回值

2.2.1 返回值是普通值

普通值:数值、字符串、普通对象、undefined等。

当返回值是一个普通值时,那么这个值就会作为一个新的Promise的resolve值

promise.then(res => {
  return "aaaaa";
  // 相当于:
  // return Promise.resolve("aaaaa");
  // return new Promise(resolve => resolve('aaaaa'));
}).then(res => {
  console.log("res:", res);// 输出:'res: aaaaa'
  return "bbbbbb"
})

2.2.2 返回一个Promise

返回一个Promise,那么后续状态是由返回的新Promise决定。

promise.then(res => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(111111)
    }, 3000);
  })
}).then(res => {
  console.log("res:", res); // res: 111111
})

2.2.3 返回拥有then方法的对象

会执行该对象上的then方法,根据执行结果返回不同状态

promise.then(res => {
  return {
    then: function (resolve, reject) {
      resolve(222222)
    }
  }
}).then(res => {
  console.log("res:", res);	// res: 222222
})

3. Promise的catch方法

普通用法不再赘述,这里讨论catch方法中传入的回调函数的返回值,情况和then方法的回调函数一样。

4. Promise 的类方法--resolve

将某个值转成Promise成功的返回值,可以使用Promise.resolve方法。

function foo() {
  const obj = { name: "fct" }
  return new Promise((resolve) => {
    resolve(obj);
  })
}

foo().then(res => {
  console.log("res:", res);
})

// 使用类方法:Promise.resolve
// resolve方法参数传入普通的值
const promise = Promise.resolve({ name: "fct" })
// 相当于
const promise2 = new Promise((resolve, reject) => {
  resolve({ name: "why" })
})

根据传递的不同类型参数(如返回Promise返回带then方法的对象),后续的状态会有不同的变化,就如前文所说。

5. Promise类方法--reject

const promise = Promise.reject("rejected message")
// 相当于
const promise2 = new Promsie((resolve, reject) => {
  reject("rejected message")
})

注意:reject方法传递什么参数值,都是一样。

const promise = Promise.reject(new Promise(() => { }));
// const promise = Promise.reject({ then() { } });

promise.then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err); // err: Promise { <pending> }
  // console.log("err:", err); // err: { then: [Function: then] }
})

6. Promise类方法--allSettled

因为all方法有一个缺陷:当有其中一个 Promise 变成 reject 状态时,all方法返回的新Promise就会立即变成对应的 reject 状态。
那么对于处于resolved、以及依然处于pending状态的Promise,我们是获取不到对应的结果的;

在ES11 (ES2020)中,添加了新的 API: Promise.allSettled
该方法会在所有的Promise都有结果(settled ),无论是 fulfilled,还是reject时,才会有最终的状态;并且这个Promise的结果一定是 fulfilled 的;

// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111)
  }, 1000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(22222)
  }, 2000);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
  }, 3000);
})

// allSettled
Promise.allSettled([p1, p2, p3]).then(res => {
  console.log(res);
  /*
  [
    { status: 'fulfilled', value: 11111 },
    { status: 'rejected', reason: 22222 },
    { status: 'fulfilled', value: 33333 }
  ] 
  */
}).catch(err => {
  console.log(err);
})

7. Promise类方法--any

any方法是ES12中新增的方法,和race方法是类似的:

  • any方法会等到一个fulfilled状态,才会决定新Promise的状态;
  • 如果所有的 Promise 都是 reject 的,那么也会等到所有的Promise都变成rejected状态,然后报出错误;
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve(11111)
    reject(1111)
  }, 1000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(22222)
  }, 500);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve(33333)
    reject(3333)
  }, 3000);
})

// any方法
Promise.any([p1, p2, p3]).then(res => {
  console.log("res:", res);
}).catch(err => {
  // console.log("err:", err) // err: AggregateError: All promises were rejected
  console.log("err:", err.errors);  // err: [ 1111, 22222, 3333 ]
})
posted @ 2021-12-25 23:19  青柠i  阅读(12)  评论(0编辑  收藏  举报