如何在 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 响应的主要内容,如果未能解决你的问题,请参考以下文章