【问题标题】:Ignoring failed promises in Promoise.all忽略 Promise.all 中失败的承诺
【发布时间】:2020-02-29 04:17:50
【问题描述】:

我正在获取数组中指定的 URL,然后合并获取的结果。 我想忽略失败的提取。

虽然有大量关于该主题的帖子:

  1. Wait until all promises complete even if some rejected
  2. https://gist.github.com/nhagen/a1d36b39977822c224b8

我只是不知道如何将它应用到我的代码中,即从数组中获取 URL:

    Promise.all (arrayOfBlobs.map (x => fetch (x).then (response => response.json())) )         
    .then (json => {
                json.forEach ( x => { 
                    if (Array.isArray (x)) {
                        // this json has array of objects
                        console.log (`Received ${x.length} prospects`)
                        x.forEach ( y => combinedArray.push (y) )   
                    }   
                    else {
                        // this json has single prospect object
                        console.log (`Received single prospect`)
                        combinedArray.push (x)
                    }
                })
        this.setState({loadingTable: false, data: combinedArray})
    })  
    .catch (error => {
        console.error (error.message)
        this.setState({loadingTable: false, data: combinedArray})
    })

例如下面的例子不起作用:

Promise.all (arrayOfBlobs.map (x => fetch (x).then (response => response.json())) )         
            .then (json => {
                        json.forEach ( x => { 
                            if (Array.isArray (x)) {
                                // this json has array of objects
                                console.log (`Received ${x.length} prospects`)
                                x.forEach ( y => combinedArray.push (y) )   
                            }   
                            else {
                                // this json has single prospect object
                                console.log (`Received single prospect`)
                                combinedArray.push (x)
                            }
                        })
                        .catch (e => {console.log (`Failed to fetch due to ${e.message}`)})
                this.setState({loadingTable: false, data: combinedArray})
            })  
            .catch (error => {
                console.error (error.message)
                this.setState({loadingTable: false, data: combinedArray})
            })

我需要做些什么来修改我的代码以便忽略失败的提取?

【问题讨论】:

  • 尝试fetch (x).then(response => response.json()).catch(() => "mark as failed") 之类的,然后过滤。

标签: reactjs promise fetch


【解决方案1】:

删除拒绝结果的 Promise.allSettled 版本:

function allFullfilled(promises) {

  const responses = [];
  let settledCount = 0;

  return new Promise(res => {

    for(const promise of promises) {

      promise
        .then( promiseResult => {
          responses.push(promiseResult);
        })
        .catch(err => {
          // ignore
        })
        .then( () => {
          settledCount++;
          if (settledCount === promises.length) {
            res(responses);
          }
        });
    }

  });

}

【讨论】:

  • 这是我只处理具有真实值的未拒绝承诺的方法: if ( ( typeof (x.value) !== "undefined") && (x.status !== "rejected ") ) {
【解决方案2】:

使用Promise.allSettled(),它将返回已完成/已拒绝的状态和值。

更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

【讨论】:

  • 这太棒了!谢谢你们俩:马特和贝格里。我现在可以看到如何完成这两项工作
【解决方案3】:

catch 应该在 map 内的个人 fetch 承诺上继续:

Promise.all(arrayOfBlobs.map(x =>
    fetch(x)
    .then(response => response.json())
    .catch(e => {
//  ^^^^^^^
        console.log(`Failed to fetch due to ${e.message}`);
        return null; // this value will get into the `json` array
    })
))         
.then(json => {
    const combinedArray = [];
    for (const x in json) { 
        if (Array.isArray(x)) {
            // this json has array of objects
            console.log (`Received ${x.length} prospects`)
            combinedArray.push(...x);
        } else if (x != null) {
            // this json has single prospect object
            console.log (`Received single prospect`)
            combinedArray.push(x)
        } else { // x == null
            console.log(`(ignored error)`)
        })
    }
    this.setState({loadingTable: false, data: combinedArray})
})

还有don't forget to handle http (status code) errors!

【讨论】:

  • 是的,它确实有效!我实际上尝试过,但是结果不是我所期望的,因此我认为我错了。这种方法将“未定义”放入组合数组中。是的,我可以过滤数组并删除未定义的值。但是我一直在寻找更优雅的解决方案:当 promise 失败时,它的结果将被完全忽略并且不会添加到组合数组中。我怀疑我确实需要过滤承诺并拒绝失败的承诺,正如我们所指出的那样。但我想过滤数组更容易。
  • 不过滤结果是没有办法的,Promise.allPromise.allSettled 都没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2016-11-25
  • 1970-01-01
  • 1970-01-01
  • 2018-09-07
  • 2017-11-01
  • 1970-01-01
相关资源
最近更新 更多