多个Promise中获取第一个成功的Promise

879 阅读2分钟

多个Promise中获取第一个成功的Promise

有这么一个需求,多张图片或者多个.mp4文件,哪一个先加载出来,就使用哪一个,加载失败的不处理。 这种需求的话就想要用到Promise来实现

多个Promise获取第一个成功的promise

一、Promise.all 改进

Promise.all(iterable)

这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。

Promise.race(iterable)

当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。

明显,Promise.allPromise.race不行,那就行改进

页面中渲染图片
<!-- 把onLoad和onError事件绑定到一起 -->
<!-- 图片一般都能正常加载,所以根据index来在src前面添加一个字符串,让链接加载失败 -->
<image onLoad="loadImg" onError="loadImg" data-index="{{index}}" a:for="{{imgarr}}" src="{{index % 2 ? 'aa' : ''}}{{item}}"/>
加载js
let prolist = []
//加载图片 成功或者失败
loadImg (e) {
  //把每一个加载图片定义一个promise,然后push到prolist数组里面
  let aPro =  new Promise((resolve, reject) => {
  	//如果图片load成功走resolve,如果加载失败走reject
    if (e.type == 'error') {
      reject(e)
    } else {
      resolve(e)
    }
  })
  prolist.push(aPro)
  //如果prolist的长度和图片数组的长度一致时,调用函数
  if (prolist.length == this.data.imgarr.length) {
    this.firstProSuccess(prolist).then(res => {
      console.log('res--》', res)
    }).catch((e) => {
      console.log('all_e', e)
    })
  }
},
//第一个成功的Promise
firstProSuccess (allProMise) {
  //遍历promise数组,根据返回值进行判断,当成功的时候,转为reject返回,当失败的时候转为resolve继续执行。
  return Promise.all(allProMise.map(item => {
    return item.then(
      res => Promise.reject(res),
      err => Promise.resolve(err)
    )
  })).then(
    errors => Promise.reject(errors),
    val => Promise.resolve(val)
  )
},
获取结果:

第一个成功的promise

二、Promise.any

Promise.any(iterable)

接收一个Promise对象的集合,当其中的一个promise 成功,就返回那个成功的promise的值。

Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promiseAggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和Promise.all()是相反的。

根据MDN上的解释这个promise.any是可以来直接使用到这个需求里面的,但是很明显这个有兼容性:

兼容性问题promise.any的兼容