Promise方法总结

132 阅读4分钟

Promise.all()

概念

Promise.all()方法将多个promise实例合成一个新的promise实例处理异步操作

all()方法参数是一个数组,里面存放promise实例

const p1 = new Promise(()=>{})
const p2 = new Promise(()=>{})
const p3 = new Promise(()=>{})

const p = Promise.all([p1,p2,p3]).then((res)=>{
  console.log(res)
}).catch(err=>console.log(err))

元素如果不是promise实例,比如是数字,字符串或者其他类型,会自动调用 Promise.resolve()转为promise实例

const p = Promise.all([1,2,3])
//数组元素 1 ,2 ,3 会被调用 Promise.resolve() 转为promise实例
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.resolve(3)
//内部会演变为这样 
const p = Promise.all([p1,p2,p3])

Promise.all()的状态依据数组里的promise实例来变化

多个实例的状态都变为fulfilled的时候,Promise.all()的状态才会变为fulfilled

如果有一个实例的状态变为rejected,Promise.all()的状态会变为rejected,第一个rejected状态的实例的返回值,会传递出来到Promise.all()的then()或者catch()回调函数上来。

const getDatas = (param) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({id: param})
    }, 1000)
  })
}

const promises = [1, 3, 4].map(id => getDatas(id))

Promise.all(promises).then((res) => {
  console.log(res)
}).catch(err => {
  console.log(err)
})

三个元素promise实例状态都变为fulfilled,或者有一个状态变为rejected,才会调用all()后面的回调函数。

Promise.all()可以确定所有请求都成功了,但是只要有一个请求失败,它就会报错,而不管另外的请求是否结束。

const p1 = new Promise((resolve, reject)=>{
  resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
  reject(234)
})
const p3 = new Promise((resolve, reject)=>{
  throw new Error('error')
})

Promise.all([p1,p2,p3]).then((results)=>{
  console.log(results)
}).catch(err=>console.log(err))

//234 
const p1 = new Promise((resolve, reject)=>{
  resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
  resolve(234)
})
const p3 = new Promise((resolve, reject)=>{
  resolve(4556)
})

Promise.all([p1,p2,p3]).then((results)=>{
  console.log(results)
})
// [123, 234, 4556]
const urls = [url_1, url_2, url_3];
const requests = urls.map(x => fetch(x));

try {
  await Promise.all(requests);
  console.log('所有请求都成功。');
} catch {
  console.log('至少一个请求失败,其他请求可能还没结束。');
}

业务场景案例

1)下面是一个常用的Promise.all()方法的案例,多个请求并发执行,然后集合统一返回处理。

const queryUserTop = ({...params}, config = {}) => {
  return post(`/partner/app/top/get`, { ...params }, config)
}

let proMap = [1, 2, 3].map(type => queryUserTop({period: 1, type}))
    Promise.all(proMap).then(res => {
      let resData = res.map(res => res?.result.ranking)
      setTopData(resData)
    }).catch((error) => {
      console.log(error)
    })

2)处理一组promise的异步请求,通过一组图片的每个前缀url,依次异步请求获取图片自己的base64码然后渲染图片

//index.vue
//template
  <li class="policy-img" v-for="(it,index) in imageInfos">
            <img :src="it.imgUrl" alt/>
            <i @click="imageInfos.splice(index,1)">×</i>
          </li>
//js methods
 const getAllImgB64Str = (imageInfos) => {
    let promiseArr = [];
    imageInfos.forEach(it => {
      let _param = {imgUrl: it.imgUrl, imgId: it.imgId}
      promiseArr.push(getImgB64StrApi(baseUrl, _param));
    });
    Promise.all(promiseArr).then(res => {
        this.imageInfos = res.map(result => {
          let temObj = {};
          if (result.code === "0200") {
            temObj.imgUrl = `data:image/png;base64,${result.data.data.imgBase64String}`;
          } else {
            this.showPosition("middle", result.data.message);
          }
          return temObj;
        });
      }).catch(err=>{
        console.log(err)
    });
  }

//调用方法
getAllImgB64Str(this.imageInfos);

Promise.race()

参数是数组,元素为多个promise实例,合成一个新的promise实例

元素不是promise实例也会执行resolve方法转成实例

不同于all()方法是元素实例中有一个状态变化,race()的实例状态会跟着执行变化,最先变化的promise实例的返回值,就传递给race()的回调函数。

如果前面的请求没有相应,5秒后走默认的异常处理

const errfun = ()=>{
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{reject(new Error('request timeout'))},5000)
  })
}
const pRace = Promise.race([fetch('abc.json'),errfun()])

pRace.then()
.catch(err=>console.log(err))

Promise.allSettled()

Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。

const p1 = new Promise((resolve, reject)=>{
  resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
  reject(234)
})
const p3 = new Promise((resolve, reject)=>{
  throw new Error('error')
})

Promise.allSettled([p1,p2,p3]).then((results)=>{
  console.log(results)
})

这个方法也是返回promise实例对象,数组内全部promise对象状态变化后,then回调函数接收返回结果,是一个数组里面映射每个成员的变化状态和结果

// 异步操作成功时
{status: 'fulfilled', value: value}

// 异步操作失败时
{status: 'rejected', reason: reason}

如果有一个promise成员状态没有变化

const p1 = new Promise((resolve, reject)=>{
  resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
  reject(234)
})
const p3 = new Promise((resolve, reject)=>{
 
})

Promise.allSettled([p1,p2,p3]).then((results)=>{
  console.log(results)
})

该方法的返回状态一直处于pending,其他结果也不会返回到then方法里面

Promise.resolve()

将现有对象转成promise对象

参数是一个promise实例

const p = new Promise((resolve, reject)=>{})
Promise.resolve(p)

const p = new Promise((resolve, reject)=>{resolve()})
Promise.resolve(p)

const p = new Promise((resolve, reject)=>{reject()})
Promise.resolve(p)

Promise.resolve 不做任何修改,原封返回实例

不带任何参数

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

const p = Promise.resolve();

p.then(function () {
  // ...
});

需要注意的是,立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。

setTimeout(function () {
  console.log('three');
}, 0);

Promise.resolve().then(function () {
  console.log('two');
});

console.log('one');

// one
// two
// three

参数是原始值,普通对象

返回一个新的promise对象,状态为fulfilled

const p = Promise.resolve('Hello');

p.then(function (s) {
  console.log(s)
});
// Hello