异步过滤一组Promises

时间:2017-12-08 12:52:34

标签: javascript asynchronous promise

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

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);
}

我从网址/' abc',网址/' cde'等,并将其保存到promises数组中。

但是,从服务器获取所有5个已解析对象的可能性很小。然后在console.log中,promises数组看起来像这样:

enter image description here

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

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

因为我对Javascript很新,所以我很感激这个Async的帮助。任何废料或代码,或建议在哪里搜索答案:)

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

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

因此,如果出现错误,它不会发送任何错误吗? 这就是为什么我可能有待处理状态而不是拒绝?

任务解决方案

嘿伙计们,所以我用两件事解决了这个问题: 1.感谢@Bergi,他指出Pending Status不是可以省略的事实 - 我检查了服务器端并且出现了第一个问题 - 错误未得到处理。 2.然后在修复服务器端之后,因为我可以将Resolved Promises与Rejected分开 - 我能够返回仅包含Resolved promises的Array - 使用这个自定义Promise_all解决方案:https://stackoverflow.com/a/46024590

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

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;
}

非常感谢所有写在这里的人!

1 个答案:

答案 0 :(得分:1)

如果你想在一定的超时后失败,你可以这样做:

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() })
      )
  );

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

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