使用Fetch API,如何在处理错误时访问JSON数据

问题描述 投票:0回答:1

我们的API服务器返回带有错误响应的JSON数据。我找不到处理错误处理方法的JSON数据的标准方法。我目前的解决方案是这个。它正在工作,但我想处理catch()方法中的错误而不是then();

let url = 'http://localhost:8080';
    let data = {'field': 'value'};
    fetch(url, {
      method: 'PUT',
      body: JSON.stringify(data),
      credentials: 'same-origin',
      mode: 'cors',
      headers: {
        'content-type': 'application/json',
        'accept': 'application/json'        
      }
    })
      .then(res => {
        if (res.status == 400) {
          return res.json();
        } else if (!res.ok) {
          throw (res);
        } else {
          return res.json();
        }
      }).then(data => {
        if (data.status == 400) {
          throw (data);
        }
        return (data);
      }).catch(err => {
        if (err.status == 400) {
          throw this.handleError(err); 
        } else {
          throw new Error(`HTTP Error ${err.status}`);
        }
      });

这是来自服务器的JSON响应的示例。

{
    "parameters": {
        "type": {
            "isEmpty": "Field is required and cannot be empty"
        },
        "from": {
            "isEmpty": "Field is required and cannot be empty"
        },
        "to": {
            "isEmpty": "Field is required and cannot be empty"
        }
    },
    "title": "Invalid parameter",
    "type": "/api/doc/invalid-parameter",
    "status": 400,
    "detail": "Invalid parameter"
}
javascript fetch-api
1个回答
1
投票

我会在fetch周围创建一个瘦的包装器,它会抛出> = 400个响应,解析后的body会解析成功的响应。

function parse(res) {
  const contentType = res.headers.get('Content-Type') || '';
  const isJson = contentType.includes('application/json');
  return isJson ? res.json() : res;
}

async function throwOnError(res) {
  if (res.status >= 400) {
    const err = new Error(res.statusText || 'Internal Server Error');
    err.status = res.status;
    const parsedRes = await parse(res);
    err.body = parsedRes;
    throw err;
  }

  return res;
}

async function fetchWrapper({ method, url, data, headers }) {
  const combinedHeaders = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
  };

  if (headers) {
    Object.assign(combinedHeaders, headers);
  }

  const options = {
    credentials: 'same-origin',
    mode: 'cors',
    method,
    headers: combinedHeaders,
  };

  if (data) {
    options.body = JSON.stringify(data);
  }

  return fetch(url, options)
    .then(throwOnError)
    .then(parse);
}

const queryParams = (params) =>
  Object.keys(params)
    .filter(k => params[k] !== null && typeof params[k] !== 'undefined')
    .map(k => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`)
    .join('&');

export const appendUrlParams = (url, params) => (params ? `${url}?${queryParams(params)}` : url);

export const $get = (url, params, { ...options }) =>
  fetchWrapper({ method: 'GET', url: appendUrlParams(url, params), ...options });

export const $del = (url, params, { ...options }) =>
  fetchWrapper({ method: 'DELETE', url: appendUrlParams(url, params), ...options });

export const $post = (url, data, { ...options }) =>
  fetchWrapper({ method: 'POST', url, data, ...options });

export const $put = (url, data, { ...options }) =>
  fetchWrapper({ method: 'PUT', url, data, ...options });

EG

async function fetchSomething() {
  try {
    const res = await $get('someurl');
    // Do something with successful `res`.
  } catch (err) {
    console.error(err);
    // err.status -> the status of the response
    // err.body -> the body of the response
  }
}

或者使用then / catch如果这是你的偏好。

© www.soinside.com 2019 - 2024. All rights reserved.