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

时间:2016-10-25 19:34:32

标签: javascript promise fetch

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

4 个答案:

答案 0 :(得分:4)

我建议使用一个检查response.ok的包装器,如果响应代码是2xx,这将是真的。

请注意MDN page on fetch()

中的此声明
  

准确检查成功获取()将包括检查   承诺解决,然后检查Response.ok属性   值为true。 HTTP状态404不构成网络   错误。

这是一个这样的包装器:

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

我找到的最佳方法是将其包装在一个新的 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 上的热门评论)

答案 3 :(得分:0)

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