概念

[Promise](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise) 是一个对象,它代表了一个异步操作的最终完成或者失败。本质上Promise是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了(这就有别于原来的ajax请求了)。
示例如下:

  1. // 成功的回调函数
  2. function successCallback(result) {
  3. console.log("音频文件创建成功: " + result);
  4. }
  5. // 失败的回调函数
  6. function failureCallback(error) {
  7. console.log("音频文件创建失败: " + error);
  8. }
  9. createAudioFileAsync(audioSettings, successCallback, failureCallback)

更现代的函数会返回一个 promise 对象,使得你可以将你的回调函数绑定在该 promise 上。
如下:

  1. const promise = createAudioFileAsync(audioSettings){
  2. return new Promise((resolve, reject) => {
  3. //resolve(someValue); // fulfilled
  4. // 或
  5. //reject("failure reason"); // rejected
  6. })
  7. };
  8. promise.then(successCallback, failureCallback);
  9. //或是
  10. promise.then(success=>{}).catch(failure=>{})

链式调用

连续执行两个或者多个异步操作是一个常见的需求,在上一个操作执行成功之后,开始下一个的操作,并带着上一步操作所返回的结果。在过去,要想做多重的异步操作,会导致经典的回调地狱:

  1. doSomething(function(result) {
  2. doSomethingElse(result, function(newResult) {
  3. doThirdThing(newResult, function(finalResult) {
  4. console.log('Got the final result: ' + finalResult);
  5. }, failureCallback);
  6. }, failureCallback);
  7. }, failureCallback);

现在,我们可以把回调绑定到返回的 Promise 上,形成一个 Promise 链:

  1. doSomething().then(function(result) {
  2. return doSomethingElse(result);
  3. })
  4. .then(function(newResult) {
  5. return doThirdThing(newResult);
  6. })
  7. .then(function(finalResult) {
  8. console.log('Got the final result: ' + finalResult);
  9. })
  10. .catch(failureCallback);

then里的参数是可选的,catch(failureCallback)then(null, failureCallback) 的缩略形式

prmoise.all

Promise.all() 方法接受一个可迭代的对象(Array,Map,Set),返回一个Promise实例。
一句话:Promise.all 等待所有都完成,或第一个失败

  1. const promise1 = Promise.resolve(3);
  2. const promise2 = 42;
  3. const promise3 = new Promise((resolve, reject) => {
  4. setTimeout(resolve, 100, 'foo');
  5. });
  6. Promise.all([promise1, promise2, promise3]).then((values) => {
  7. console.log(values);
  8. });
  9. // Array [3, 42, "foo"]

当传入的异步请求全部完成时返回 返回一个完成的promise。
当传入的异步请求有一个reject了,或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。并且不会再管其它 promise 是否完成
所以,当我们有多个异步请求,且在业务逻辑上他们有一定相关性就可以用promise.all()来统一请求

Promise.allSettled

Promise.all() 方法接受一个可迭代的对象(Array,Map,Set),返回一个Promise实例。
当多个彼此不依赖的异步任务时,或者是想知道每个promise的结果时,通常使用它。这就是他与 Promise.all的最大区别,不管传入的异步请求是不是全部都成功了,都会返回每一个的请求结果。而peomise.all遇到错误就会直接返回错误

对于每个结果对象,都有一个 status 字符串。如果它的值为 fulfilled,则结果对象上存在一个 value 。如果值为 rejected,则存在一个 reason ,如下:

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject('错误了'), 100));
const promises = [promise1, promise2];

Promise.allSettled(promises).then((results) => console.log(results))

//{status: 'fulfilled', value: 3}
//{status: 'rejected', reason: '错误了'}

Promise.race()

方法接受一个可迭代的对象(Array,Map,Set),返回一个Promise实例。
一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
实际的作用就是看哪一个promise先跑出来

var p1 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 500, "one");
});
var p2 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, "two");
});

Promise.race([p1, p2]).then(function(value) {
  console.log(value); // "two"
  // 两个都完成,但 p2 更快
});

var p3 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, "three");
});
var p4 = new Promise(function(resolve, reject) {
    setTimeout(reject, 500, "four");
});

Promise.race([p3, p4]).then(function(value) {
  console.log(value); // "three"
  // p3 更快,所以它完成了
}, function(reason) {
  // 未被调用
});

var p5 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 500, "five");
});
var p6 = new Promise(function(resolve, reject) {
    setTimeout(reject, 100, "six");
});

Promise.race([p5, p6]).then(function(value) {
  // 未被调用
}, function(reason) {
  console.log(reason); // "six"
  // p6 更快,所以它失败了
});

promise.any

Promise.any() 接收一个可迭代对象(Array,Map,Set),只要其中的一个 promise 成功,就返回那个已经成功的 promise。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise。如下例子:

const pErr = new Promise((resolve, reject) => {
  reject("总是失败");
});

const pSlow = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "最终完成");
});

const pFast = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "很快完成");
});

Promise.any([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
})
//很快完成

promise.any 与 promise.all的区别就在于:all是要全部都是resolve了 才会返回一个resolve。这个是其中任何一个resolve就返回resolve。
promise.any 与 promise.race的区别就在于:race是用第一个返回的promise来返回,不论是resolve还reject。any是用第一个成功状态的 promise 来返回

参考

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises 本文基本是这篇文章的学习笔记