【问题标题】:How to handle successive axios.get in Promise?Promise中如何处理连续的axios.get?
【发布时间】:2018-11-21 17:47:51
【问题描述】:

我有这样的数据:

const resultData = {};
const data = {
  'foo': 'https://valid/url/1',
  'bar': 'https://valid/url/2',
  'baz': 'https://INVALID/url/3',
};

我想向每个网址发出 GET 请求。

如果请求成功,我想将响应添加到 resultData 。 如果没有,什么也不做,也不要引发任何错误。

resultData 会是这样的:

resultData = {
  'foo': { ...responseOfFoo },
  'bar': { ...responseOfBar },
};

我写了一个类似下面的代码,但这并没有意识到我想要做什么。

当请求失败并返回 404 时,axios 会引发错误,此外,async/await 似乎无法正常工作。

import _ from 'lodash';

return new Promise((resolve, reject) => {
  const resultData = {};
  _.forEach(data, async (url, key) => {
    const res = await axios.get(url).catch(null);
    resultData[key] = res.data;
  });

  resolve(resultData);
});

这有什么问题?

我也尝试使用axios.allPromise.all,但无法正确处理请求的每个错误。

【问题讨论】:

    标签: javascript promise axios


    【解决方案1】:

    使用 Promise.all 并将 .catch() 错误处理程序附加到每个 GET 请求的末尾,这样如果它们抛出错误,它就会在 Promise.all 对结果进行分组之前被捕获。

    类似:

    const data = {
      'foo': 'https://valid/url/1',
      'bar': 'https://valid/url/2',
      'baz': 'https://INVALID/url/3',
    };
    Promise
    .all(
        Object
        .entries( data )
        .map(({ name, url }) => axios
            .get( url )
            .catch( error => {
                throw new Error( `Failed GET request for ${ name }` );
                // Individual GET request error handler.
            })
        )
    )
    .then( results => {
    
    })
    .catch( error => {
        //  error on the Promise.all level, or whatever an individual error handler throws.
        //  So if the url of foo rejects, it will get thrown again by the catch clause after .get()
        //  So the error would be 'Failed GET request for foo'.
    });
    

    如果你在 GET 请求的 catch 子句中抛出错误,错误将冒泡到 Promise.all() 之后的 catch 子句

    如果你从 catch 子句中返回一个值,那将是 get 请求的结果,然后在 results 数组中,所以你仍然可以使用成功的两个请求。

    如果“获取请求”之一失败,以下示例将仅返回一个描述问题的对象,并将一起检查结果的有效性。

    Promise
    .all([
      Promise.resolve( 'ok1' ).then( result => ({ "status": "ok", "value": result })),
      Promise.resolve( 'ok2' ).then( result => ({ "status": "ok", "value": result })),
      Promise.reject( 'nok3' ).catch( error => ({ "status": "nok", "value": error }))
    ])
    .then( results => {
      results.forEach(( result, index ) => {
        if ( result.status === 'ok' ) console.log( `promise ${ index } resolved correctly: ${ result.value }`);
        else console.log( `promise ${ index } rejected with error: ${ result.value }` );
      });
    })
    .catch( error => console.error( error ));

    如果您需要能够单独处理 GET 请求错误并且仍然触发其余 url 的 .then() 子句,那么您实际上无法将所有请求一起批处理。

    【讨论】:

    • 谢谢,但是如果任何一个 url 返回 404,我怎么能忽略这个错误呢?就像我的问题一样,即使'baz': 'https://INVALID/url/3' throws not found,其余数据也会插入到resultData
    • 不要重投catch
    • 您可以用您希望的任何错误处理替换我重新抛出错误的 catch 子句,例如检查状态代码等。我想说的是,您可以在那里捕获单个 GET 请求错误。如果您想在 Promise.all 之后将错误“冒泡”到 catch 子句,例如在不同级别进行进一步的错误处理,您可以在 GET 请求的捕获中抛出一个新错误,这样它就会冒泡通过承诺链。
    • 好的,即使我将.catch(null) 附加到每个axios.get 似乎也不起作用,但我会尝试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    相关资源
    最近更新 更多