如何在 fetch api 中处理 HTTP 代码 4xx 响应

Posted

技术标签:

【中文标题】如何在 fetch api 中处理 HTTP 代码 4xx 响应【英文标题】:How to handle HTTP code 4xx responses in fetch api 【发布时间】:2017-03-07 23:46:26 【问题描述】:

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

【问题讨论】:

400?一个适当的解决方法可能是重新设计一种全新的方式来获取数据。也许用参数发出 1 个请求,并让 API 将所有数据拼凑在一起。 @CoreyOgburn 我相信 OP 的意思是 4xx HTTP 错误代码。 @TomG 这更有意义。 是的,我的意思是400错误代码,例如有人登录时密码无效 实际上,@ArturKasperek,我认为无效密码会正确抛出 409 冲突状态:服务器能够处理该请求,但发现存在与资源相关的问题(即用户)。 【参考方案1】:

将它合并到您的 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() 也不是一个好主意。在某些方面,它类似于全局变量。

【讨论】:

【参考方案2】:

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

请注意MDN page on fetch()中的此声明:

对成功的 fetch() 的准确检查包括检查 承诺已解决,然后检查 Response.ok 属性是否已 值为真。 404的HTTP状态不构成网络 错误。

这是一个这样的包装器:

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
    )

【讨论】:

【参考方案3】:

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

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

【讨论】:

【参考方案4】:

我为此找到的最佳方法是将其包装在一个新的 Promise 中,如果 response.ok 为 false,则拒绝带有错误上下文的 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的最高评论)

【讨论】:

以上是关于如何在 fetch api 中处理 HTTP 代码 4xx 响应的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 中处理 fetch API AJAX 响应

如何使用 Redux Thunk 处理 fetch() 响应中的错误?

如何在 React 中使用 fetch 正确处理来自 REST API 的数据对象

javascript 如何使用fetch处理api超时

PWA系列——Fetch API

如何使用 express js 处理 fetch API 请求