如何处理提取中的 HTTP 代码 4xx 响应 api

How to handle HTTP code 4xx responses in fetch api

我想知道当我们使用 ajax 函数时,我们应该如何从后端处理 400。我们可以在 promise 解析函数中创建 if 语句,并检查 res 状态是否为 400。不同的方法是为获取创建包装服务,当我们从服务器获得 400 时,我们抛出异常。如何处理这个问题?

将它合并到您的 HTTP 抽象中可能是个好主意。也许有某种 options 论点:

const myFetch = (method, path, {headers, strictErrors, whatever}) => {
  // fetch here, if strictErrors is true, reject on error.
  // return a Promise.
}

myFetch('GET', 'somepath', {strictErrors: true})
  .then(response => {})
  .catch(err => { /* maybe 400 */ });

围绕 fetch 的包装通常是个好主意,fetch 是一个相对较低级别的函数。正如在所有地方直接创建新的 XHR 对象不是一个好主意一样,我认为在应用程序的各个部分直接调用 fetch() 也不是一个好主意。在某些方面,它类似于全局变量。

我建议使用一个包装器来检查 response.ok 如果响应代码为 2xx,则为真。

请注意来自 MDN page on fetch() 的声明:

An accurate check for a successful fetch() would include checking that the promise resolved, then checking that the Response.ok property has a value of true. An HTTP status of 404 does not constitute a network error.

这是一个这样的包装器:

function fetchData() {
    return fetch.apply(null, arguments).then(response => {
         if (!response.ok) {
             // create error object and reject if not a 2xx response code
             let err = new Error("HTTP status code: " + response.status)
             err.response = response
             err.status = response.status
             throw err
         }
         return response
    })
}

这样我们就可以相应地处理所有类型的状态。

fetch(url, {
  method: 'POST',
  headers: headers,
  body: JSON.stringify({ user_email: email }),
}).then((response) => {
  return new Promise((resolve) => response.json()
    .then((json) => resolve({
      status: response.status,
      ok: response.ok,
      json,
    })));
}).then(({ status, json, ok }) => {
  const message = json.message;
  let color = 'black';
  switch (status) {
    case 400:
      color = 'red';
      break;
    case 201:
    case 200:
      color = 'grey';
      break;
    case 500:
    default:
      handleUnexpected({ status, json, ok });
  }
})

inspiration

为此我找到的最佳方法是将其包装在一个新的 Promise 中,如果 response.ok 为假,则拒绝带有错误上下文的 Promise。

/**
 * Parses the JSON returned by a network request
 *
 * @param  {object} response A response from a network request
 *
 * @return {object}          The parsed JSON, status from the response
 */
function parseJSON(response) {
  return new Promise((resolve) => response.json()
    .then((json) => resolve({
      status: response.status,
      ok: response.ok,
      json,
    })));
}

/**
 * Requests a URL, returning a promise
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 *
 * @return {Promise}           The request promise
 */
export default function request(url, options) {
  return new Promise((resolve, reject) => {
    fetch(endpoint  + url, options)
      .then(parseJSON)
      .then((response) => {
        if (response.ok) {
          return resolve(response.json);
        }
        // extract the error from the server's json
        return reject(response.json.meta.error);
      })
      .catch((error) => reject({
        networkError: error.message,
      }));
  });
}

https://github.com/github/fetch/issues/203 上的热门评论)