繁体   English   中英

使用 Promise.allSettled 捕获被拒绝的 Promise 的请求响应代码

[英]Capture request response code of rejected promises with Promise.allSettled

我正在使用Promise.allSettled来调用 URL 数组,我需要捕获被拒绝承诺的请求的响应代码。 使用result.reason提供的Promise.allSettled的值不足以准确评估拒绝 promise 的原因。 我需要请求响应代码(400、500、429 等)。

到目前为止,我有以下内容:

var response = await Promise.allSettled(urls.map(url => fetch(url)))
    .then(results => {
        var data = [];
        results.forEach((result, num) => {
            var item = {
                'req_url': urls[num],
                'result': result.status,
                'result_details': result
            };
            data.push(item);
        });
        return data;
    });

如何捕获被拒绝的 promise 请求的响应代码并将其作为属性添加到返回的数组中? 返回的数组应该看起来像这样:

[{
    'req_url': 'https://myurl.xyz/a',
    'req_status_code': 400,
    'result': 'rejected',
    'result_details': {
        'status': 'rejected',
        'message': 'TypeError: Failed to fetch at <anonymous>:1:876'
    }
},
{
    'req_url': 'https://myurl.xyz/b',
    'req_status_code': 419,
    'result': 'rejected',
    'result_details': {
        'status': 'rejected',
        'message': 'TypeError: Failed to fetch at <anonymous>:1:890'
    }
},
{
    'req_url': 'https://myurl.xyz/c',
    'req_status_code': 429,
    'result': 'rejected',
    'result_details': {
        'status': 'rejected',
        'message': 'TypeError: Failed to fetch at <anonymous>:1:925'
    }
}]

有任何想法吗?

fetch不会在 HTTP 故障时拒绝其 promise,只有网络故障。 (在我看来,这是一个 API 枪,几年前我在我贫血的旧博客上 写过。)我通常通过将fetch包装在 HTTP 故障时拒绝的东西来解决这个问题。 您也可以这样做,并根据拒绝原因提供失败状态。 (但您不必这样做,请参见下文。)

class FetchError extends Error {
    constructor(status) {
        super(`HTTP error ${status}`);
        this.status = status;
    }
}
async function goFetch(url, init) {
    const response = await fetch(url, init);
    if (!response.ok) {
        // HTTP error
        throw new FetchError(response.status);
    }
    return response;
}

Then you could pass an async function into map to handle errors locally, and use Promise.all (just because doing it all in one place is simpler than doing it in two places with Promise.allSettled ):

const results = await Promise.all(urls.map(async url => {
    try {
        const response = await goFetch(url);
        // ...you might read the response body here via `text()` or `json()`, etc...
        return {
            req_url: url,
            result: "fulfilled",
            result_details: /*...you might use the response body here...*/,
        };
    } catch (error) {
        return {
            req_url: url,
            result: "rejected",
            result_status: error.status, // Will be `undefined` if not an HTTP error
            message: error.message,
        };
    }
}));

或者您可以在没有fetch包装器的情况下执行此操作:

const results = await Promise.all(urls.map(async url => {
    try {
        const response = await fetch(url);
        if (!response.ok) {
            // Local throw; if it weren't, I'd use Error or a subclass
            throw {status: response.status, message: `HTTP error ${response.status}`};
        }
        // ...you might read the response body here via `text()` or `json()`, etc...
        return {
            req_url: url,
            result: "fulfilled",
            result_details: /*...you might use the response body here...*/,
        };
    } catch (error) {
        return {
            req_url: url,
            result: "rejected",
            result_status: error.status, // Will be `undefined` if not an HTTP error
            message: error.message,
        };
    }
}));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM