簡體   English   中英

如何在 fetch api 中處理 HTTP 代碼 4xx 響應

[英]How to handle HTTP code 4xx responses in fetch api

我想知道當我們使用 ajax 函數時我們應該如何處理來自后端的 400 。 我們可以在 promise resolve 函數中創建 if 語句並檢查 res 狀態是否為 400。不同的方法是為 fetch 提供包裝服務,當我們從服務器獲得 400 時,我們拋出異常。 如何處理那個問題?

我建議使用一個檢查response.ok的包裝器,如果響應代碼為 2xx,這將是正確的。

請注意fetch()上 MDN 頁面中的此語句:

對成功的 fetch() 的准確檢查將包括檢查 promise 是否已解決,然后檢查 Response.ok 屬性的值是否為 true。 HTTP 狀態 404 不構成網絡錯誤。

這是一個這樣的包裝器:

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 });
  }
})

靈感

我為此找到的最佳方法是將其包裝在一個新的 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上發表評論)

將它合並到您的 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()也不是一個好主意。 在某些方面,它類似於全局變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM