一、Promise的一些办法

1.Promise.race()

(1)简介:Promise.race()办法是将多个Promise实例,包装成一个新的Promise实例

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

只有p1, p2, p3之中有一个实例的状态率先产生扭转,p的状态就跟着扭转。

那率先扭转的Promise实例的返回值,就传递给p的回调函数。

(2)参数:和Promise.all()的参数一样,是一个元素为Promise对象的数组

(3)返回值:一个新的Promise对象

(4)留神点:

  • Promise.race()办法如果传入的参数不是Promise实例,就会先调用Promise.resolve()办法,将参数转成Promise实例,再进一步解决。
  • 只有参数中有其中的一个Promise状态产生扭转,新生成的Promise对象的状态也会随之产生扭转。上面的例子就是这样:
const p = Promise.race([  fetch('/resource-that-may-take-a-while'),  new Promise(function (resolve, reject) {    setTimeout(() => reject(new Error('request timeout')), 5000)  })]);p.then(console.log).catch(console.error);

下面代码中,如果 5 秒之内fetch办法无奈返回后果,变量p的状态就会变为rejected,从而触发catch办法指定的回调函数。

2.Promise.allSettled()

(1)简介:Promise.allSettled()办法承受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回后果,不论是fulfilled还是rejected,包装实例才会完结。该办法由 ES2020 引入。

const promises = [  fetch('/api-1'),  fetch('/api-2'),  fetch('/api-3'),];await Promise.allSettled(promises);removeLoadingIndicator();

下面代码对服务器收回三个申请,等到三个申请都完结,不论申请胜利还是失败,加载的滚动图标就会隐没。

(2)参数:和Promise.all()的参数一样,是一个元素为Promise对象的数组

(3)返回值:一个新的Promise对象

(4)和Promise.all()区别:

  • Promise.allSettled()必须要等到所有传入的Promise状态变为fullfilled还是rejected,能力返回一个Promise对象。Promise.all()返回Promise对象的条件有二:一是所有的Promise的状态都变为fullfilled,二是其中的一个Promise的状态变为rejected
  • Promise.allSettled()的返回值allSettledPromise,状态只可能变成fulfilled。Promise.all()则是要求传入的所有Promise对象的状态都变为fullfilled时,返回的对象的状态能力为fullfilled,如果其中的一个Promise对象的状态变为rejected,返回的对象的状态就会变为rejected。
const resolved = Promise.resolve(42);const rejected = Promise.reject(-1);//allSettledPromise的状态只可能变成fullfilledconst allSettledPromise = Promise.allSettled([resolved, rejected]);allSettledPromise.then(function (results) {  console.log(results);});// [//    { status: 'fulfilled', value: 42 },//    { status: 'rejected', reason: -1 }// ]

(5)应用场景

有时候,咱们不关怀异步操作的后果,只关怀这些操作有没有完结。比方在申请某些图片的过程中显示加载中...,这时候咱们并不去关怀图片到底有没有胜利返回,咱们只须要关怀申请这个操作是否完结。这时,Promise.allSettled()办法就很有用。如果没有这个办法,想要确保所有操作都完结,就很麻烦。Promise.all()办法就不能做到这一点。请看上面的例子:

const urls = [ /* ... */ ];const requests = urls.map(x => fetch(x));try {  await Promise.all(requests);  console.log('所有申请都胜利。');} catch {  console.log('至多一个申请失败,其余申请可能还没完结。');}

下面代码中,Promise.all()无奈确定所有申请都完结。想要达到这个目标,写起来很麻烦,有了Promise.allSettled(),这就很容易了。

3.Promise.any()

(1)简介:Promise.any()办法承受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

请看上面的这个例子:

var resolved = Promise.resolve(42);var rejected = Promise.reject(-1);var alsoRejected = Promise.reject(Infinity);Promise.any([resolved, rejected, alsoRejected]).then(function (result) {  console.log(result); // 42});Promise.any([rejected, alsoRejected]).catch(function (results) {  console.log(results); // [-1, Infinity]});

(2)参数:和Promise.all()的参数一样,是一个元素为Promise对象的数组

(3)返回值:一个新的Promise对象

(4)区别:

  • 和Promise.all()的区别:能够说是和Promise.all()刚好相同,Promise.all()是所有的Promise的状态都变为fullfilled时,返回的Promise对象的状态才会变成fullfilled,然而如果其中一个Promise状态变为rejected,返回的Promise的状态就马上变为rejected。
  • 和Promise.race()的区别:Promise.any()跟Promise.race()办法很像,只有一点不同,就是不会因为某个 Promise 变成rejected状态而完结。而Promise.race()如果有其中的一个Promise对象的状态扭转,返回的Promise对象的状态将会随着扭转的Promise对象的状态的扭转而扭转。

4.Promise.try()

理论开发中,常常遇到一种状况:不晓得或者不想辨别,函数f是同步函数还是异步操作,然而想用 Promise 来解决它。因为这样就能够不论f是否蕴含异步操作,都用then办法指定下一步流程,用catch办法解决f抛出的谬误。个别就会采纳上面的写法。

Promise.resolve().then(f)

下面的写法有一个毛病,就是如果f是同步函数,那么它会在本轮事件循环的开端执行。

const f = () => console.log('now');Promise.resolve().then(f);console.log('next');// next// now

如果想要解决这个问题,能够应用Promise.try对f进行包装,这样就能够保障同步函数同步执行,异步函数异步执行。

const f = () => console.log('now');Promise.try(f);console.log('next');// now// next

另外,Promise.then()尽管能够捕捉Promise对象抛出的异步谬误,然而却捕捉不了同步谬误,看上面的例子:

function getUsername(userId) {  return database.users.get({id: userId})  .then(function(user) {    return user.name;  });}.catch((e) => console.log(e));

下面代码中,database.users.get()返回一个 Promise 对象,如果抛出异步谬误,能够用catch办法捕捉.

然而,如果database.users.get()抛出了同步谬误(比方数据库链接谬误等),catch就不能捕捉到这个谬误,这时就不得不应用try...catch去捕捉,就像这样:

try {  database.users.get({id: userId})  .then(...)  .catch(...)} catch (e) {  // ...}

然而,如果应用Promise.try()就能够对立应用catch捕捉同步或者是异步谬误

Promise.try(() => database.users.get({id: userId}))  .then(...)  .catch(...)

我的了解就是Promise.try就是模仿try代码块,就像promise.catch模仿的是catch代码块。

5.Promise.resolve()

(1)简介:Promise.resolve()将现有的对象或其余转化为一个Promise对象。上面是一个应用Promise.resolve()的例子:

const jsPromise = Promise.resolve($.ajax('/whatever.json'));        //jsPromise是一个Promise对象

下面代码将jQuery生成的deferred对象转成一个新的Promise对象。

Promise.resolve()等价于上面的写法:

Promise.resolve('foo')//等价于new Promise((resolve) => resolve('foo'));

(2)参数:

  • 参数是一个Promise实例

    如果参数是 Promise 实例,那么Promise.resolve将不做任何批改、一成不变地返回这个实例。

  • 参数是一个thenable对象

    thenable对象是指具备then办法的对象,比方上面这个对象。

//这是一个thenable对象let thenable = {  then: function(resolve, reject) {    resolve(42);  }};//应用Promise.resolve()办法let p1 = Promise.resolve(thenable);            //会立刻执行then办法p1.then(function(value) {  console.log(value);  // 42});

留神:Promise.resolve()办法会立刻执行thenable对象外面的then办法,而后将对象p1的状态变为resolved,从而执行p1.then()办法,输入42.

  • 参数不是具备then办法的对象,或基本就不是对象

    如果参数是一个原始值,或者是一个不具备then办法的对象,则Promise.resolve办法返回一个新的 Promise 对象,状态为resolved。

const p = Promise.resolve('Hello');        //p的状态肯定会变成resolvedp.then(function (s){  console.log(s)});// Hello

下面代码生成一个新的 Promise 对象的实例p。因为字符串Hello不属于异步操作(判断办法是字符串对象不具备 then 办法),返回 Promise 实例的状态从毕生成就是resolved,所以回调函数会立刻执行。Promise.resolve办法的参数,会同时传给回调函数。

  • 不带有任何参数

    Promise.resolve()办法容许调用时不带参数,间接返回一个resolved状态的 Promise 对象。

const p = Promise.resolve();            //p的状态肯定会变成resolvedp.then(function () {  // ...});

留神:立刻resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的完结时执行(微工作),而不是在下一轮“事件循环”的开始时。

//setTimeout是宏工作,在下一轮事件循环才执行setTimeout(function () {  console.log('three');}, 0);//微工作,在本轮事件循环完结的时候执行Promise.resolve().then(function () {  console.log('two');});console.log('one');// one// two// three

下面代码中,setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.resolve()在本轮“事件循环”完结时执行,console.log('one')则是立刻执行,因而最先输入。

6.Promise.reject()

(1)简介:Promise.reject(reason)办法也会返回一个新的 Promise 实例,该实例的状态为rejected

const p = Promise.reject('出错了');// 等同于const p = new Promise((resolve, reject) => reject('出错了'))p.then(null, function (s) {  console.log(s)});// 出错了

下面代码生成一个 Promise 对象的实例p,状态为rejected,回调函数会立刻执行。

(2)留神:

留神,Promise.reject()办法的参数,会一成不变地作为reject的理由,变成后续办法的参数。这一点与Promise.resolve办法不统一。

const thenable = {  then(resolve, reject) {    reject('出错了');  }};Promise.reject(thenable).catch(e => {  console.log(e === thenable)})// true

下面代码中,Promise.reject办法的参数是一个thenable对象,执行当前,前面catch办法的参数不是reject抛出的“出错了”这个字符串,而是thenable对象。