【问题标题】:Javascript Promises in a loop循环中的 Javascript Promise
【发布时间】:2018-06-23 07:19:33
【问题描述】:

我有一个名为 _problemFunction 的函数,它接受一个数组 myList 作为参数。对于 myList 中的每个项目,我调用一个函数 _myFunction_myFunction 返回一个承诺。如果_myFunction 使用我列表中的任何项目返回resolve,我想从_problemFunction 返回resolve。如果_myFunction 为myList 中的所有项目返回reject,我想从_problemFunction 返回reject。下面是场景的代码块:

_problemFunction = (myList) => {
  return new promise((resolve, reject) => {
    myList.forEach(listItem => {
      _myFunction(listItem).then(pass => {
        //Resolve when _myFunction returns resolve with any listitem argument  
      }).catch(fail => {
        //reject only if _myfunction returns rejects for all the listitems
      })
    })
  })
}

【问题讨论】:

    标签: javascript node.js es6-promise


    【解决方案1】:

    据我所知,只有在所有承诺都拒绝时,您才想拒绝,因此您必须知道拒绝是否与运行拒绝回调的数组长度相同,如下所示:

        return new promise((resolve, reject) => {
       let rejectCount = 0
       let resolved = false
       for(let listItem of myList){
          _myFunction(listItem).then(pass => {
            //Resolve when _myFunction returns resolve with any listitem argument
            if(!resolved){ 
             resolved = true
             resolve(pass) 
            }
          }).catch(fail => {
            //reject only if _myfunction returns rejects for all the listitems
            rejectCount++
            if(rejectCount === myList.length) {
              reject(fail)
            }
          })
          if(resolved) break
       }
    })
    

    如果您有列表为空或未定义的极端情况,您可以在 for 循环之前添加此检查:

    if(!myList || myList.length === 0) {
        reject(new Error('list is empty or undefined')
        return
    }
    

    【讨论】:

    • 有一种极端情况,myList 是一个空数组或字符串,promise 永远不会被解析或拒绝。
    【解决方案2】:

    这取决于您是要并行还是串行执行列表中的所有项目:

    要解决第一个解决并拒绝所有系列错误的项目:

    //serial resolve on first resolved item
    _problemFunction = (myList,failed=[]) => {
      if(myList.length===0){
        return Promise.reject(failed);
      }
      return _myFunction(myList[0])
      .catch(
        //try it again with the next item
        err=>_problemFunction(myList.slice(1),failed.concat([err]))
      )
    }
    

    一次尝试并返回首先解决的任何问题,但拒绝所有失败的解决方案(除非您的列表为空,否则它将失败并返回一个空列表)

    //parallel resolve on first resolved item reject when all reject
    _problemFunction = (myList,failed=[]) => {
      if(failed.length===0){
        myList = myList
        .map(([item,index])=>
          [
            index,
            _myFunction(item)
            .catch(err=>Promise.reject([err,index]))
          ]
        );
      }
      if(myList.length===0){
        return Promise.reject(failed);
      }
      return Promise.race(
        myList.map(([i,p])=>p)
      )
      .catch(
        ([err,index])=>//an error remove the failed item and try again
          _problemFunction(
            myList.filter(([i,p])=>i!==index),
            failed.concat([err])
          )
      )
    }
    

    【讨论】:

      【解决方案3】:

      看看 Promise.all() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

       let request = data.map((i) => {
          return new Promise((resolve, reject) => {
             if(i < 1) {
                reject('value to low')
             }
              resolve(i);
          }); });
          return  Promise.all(data) });
      

      【讨论】:

        【解决方案4】:
            _problemFunction = (myList) => {
          return new promise((resolve, reject) => {
            const errs = [];
            myList.forEach(listItem => {
              _myFunction(listItem)
              .then(resolve)
              .catch(fail => {
                errs.push(fail);
                errs.length === myList.length ? reject(errs) : '';
              })
            })
          })
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-06-25
          • 2018-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-06
          • 1970-01-01
          相关资源
          最近更新 更多