异步过滤一组Promises [英] Asynchronous filtering an array of Promises

查看:74
本文介绍了异步过滤一组Promises的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个字符串数组 let symbol = ['abc','cde','edf','qqe','hrt'] ,我将其作为参数传递给该函数:

I have an array of strings let symbols = ['abc', 'cde', 'edf', 'qqe', 'hrt'] that I pass as an argument to the function:

async function fetchDetails(symbols) {
  let promises = symbols.map((s, i) => {
    return fetch(URL + s)
      .then(res => return res.json())
      .then(json => Object.assign({}, { [s]: json }))
  });
  console.log('promise:', promises)
  return Promise.all(promises);
}

我从URL/'abc',URL/'cde'等获取数据,并将其保存到promises数组中.

I fetch data from URL/'abc', URL/'cde' etc. and save it into promises array.

但是从服务器我不会获得全部5个已解析对象的可能性为%.然后在console.log中,promises数组如下所示:

But there is an % probability that from the server I will not get all 5 resolved objects. Then in console.log the promises array looks like this:

我想让数组仅包含4个已解决的项目(我将其传递给Promise.all(),而不是5个(包括4个已解决的项目和1个具有待处理状态的项目).

And I would like to have array containg only 4 resolved items (that I pass to the Promise.all(), instead of 5 (including 4 resolved and 1 with pending status).

如果它是一个同步函数,我只需要过滤数组即可.但是我无权访问[[PromiseStatus]]属性,也不知道如何执行此操作.

If it was a synchronous function, I would simply have to have filtered the array. But I have no access to the [[PromiseStatus]] properties and have no idea how to do this.

由于我是Java语言的新手,所以希望您对Async有所帮助.任何剪贴簿留言或代码,或建议在哪里搜索答案:)

Since I am quite new to the Javascript I would appreciate any help with this Async thing. Any scrap or code, or advise where to search for the answer :)

修改:也许这会有所帮助,我将查询发送到的路由是这样构建的:

Edit: Maybe this will help a bit, the route I send a query to, is built like this:

app.get('/data/:symbol', async (req, res) => {
  const { params: { symbol } } = req
  const data = await stocks.getData(symbol, new Date())
  res.send(data)
})

因此,在出现错误的情况下,它不会发送任何错误信息吗?这就是为什么我可能有待处理状态而不是拒绝的原因?

So in the case of error, it doesn't send any error right? And that's why I could potentially have Pending Status instead of Reject?

解决方案

大家好,所以我用两件事解决了这个问题:1.感谢@Bergi,他指出了Pending Status不能被忽略的事实-我检查了服务器端,这是第一个问题-错误没有得到处理.2.然后在修复服务器端之后,由于我可以将已解决的承诺"与已拒绝的"分开-我很想使用此自定义Promise_all解决方案返回仅包含已解决的承诺"的数组:> https://stackoverflow.com/a/46024590

Hey guys, so I solved this issue with 2 things: 1. Thanks to @Bergi, who pointed to the fact that Pending Status is not something that can be omitted - I checked server side and there was a first problem - Errors were not handled. 2. Then after fixing Server side, since I could separate Resolved Promises from Rejected - I was abble to return Array containing only Resolved promises - using this custom Promise_all solution: https://stackoverflow.com/a/46024590

所以我的最终代码看起来像这样:

So my final code looks something like this:

async function fetchDetails(symbols) {
  let promises = symbols.map(async (s, i) => {
    return await fetch(URL + s)
      .then((res)=> {
        if (!res.ok) {
          throw new Error('Error with fetch')
        } else {
          return res.json();
        }
      })
      .then(json => Object.assign({}, { [s]: json })) 
      .catch(err => {
        return Promise.reject()})    
  });

  const Promise_all = promises => {
    return new Promise((resolve, reject) => {
      const results = [];
      let count = 0;
      promises.forEach((promise, idx) => {
        promise
          .catch(err => {
            return err;
          })
          .then(valueOrError => {
            results[idx] = valueOrError;
            count += 1;
            if (count === promises.length) resolve(results);
          });
      });
    });
  }; 

  const results = await Promise_all(promises)
  const validResults = results.filter(result => result !== undefined);

  return validResults;
}

非常感谢在这里写信的每个人!

推荐答案

如果您希望在某个超时后失败,可以执行以下操作:

If you want to fail after a certain timeout you could do this:

const failIn = milliseconds =>
  setTimeout(
    _=>Promise.reject("timed out")
    ,milliseconds
  );

const Fail = function(details){this.details=details;};

const fetchDetails = symbols =>
  Promise.all(
    symbols.map((s, i) => {
      return Promise.race([
        fetch(URL + s),
        ,failIn(2000)//fail in 2 seconds
      ])
      .then(
        response=>[response,s],
        err = [new fail([err,URL+s]),s]
      )
    })
  )
  .then(
    responses =>
      responses.map(//map to json object from response or Fail type
        ([response,s]) => 
          (response && response.constructor === Fail)
            ? response
            : Object.assign({}, { [s]: response.json() })
      )
  );

失败对象仍包含在结果中,如果您只是想忽略它们,则可以使用过滤器将它们取出:

The Fail objects are still included in the result, you could use filter to take them out if you're just going to ignore them:

  .then(
    responses =>
      responses.filter(
        ([response,s]) => (response && response.constructor !== Fail)
      )
      .map(
        ([response,s]) => 
          Object.assign({}, { [s]: response.json() })
      )
  )

这篇关于异步过滤一组Promises的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆