1. 程式人生 > 實用技巧 >umi-request Ant Pro 的請求庫

umi-request Ant Pro 的請求庫

umi-request

umi-request 是基於 fetch 的封裝,兼具 fetch 和 axios 的特點。旨在為開發者提供便捷統一的請求方式。Ant Pro 中對 其進行了初步的封裝。比如:統一的錯誤處理方式。

但是,在實際中我們可能會遇見各種各樣的情況,需要按照自己的需求對其進行封裝。那就首先從 Ant Pro 的統一的異常處理程式開始吧。
首先,引入umi-request的擴充套件到專案中。

import { extend } from 'umi-request';

其次,根據自己的專案實際情況定義錯誤碼和其對應的提示語。

const codeMessage = {
  200: '伺服器成功返回請求的資料。',
  201: '新建或修改資料成功。',
  202: '一個請求已經進入後臺排隊(非同步任務)。',
  204: '刪除資料成功。',
  400: '發出的請求有錯誤,伺服器沒有進行新建或修改資料的操作。',
  401: '使用者沒有許可權(令牌、使用者名稱、密碼錯誤)。',
  403: '使用者得到授權,但是訪問是被禁止的。',
  404: '發出的請求針對的是不存在的記錄,伺服器沒有進行操作。',
  406: '請求的格式不可得。',
  410: '請求的資源被永久刪除,且不會再得到的。',
  422: '當建立一個物件時,發生一個驗證錯誤。',
  500: '伺服器發生錯誤,請檢查伺服器。',
  502: '閘道器錯誤。',
  503: '服務不可用,伺服器暫時過載或維護。',
  504: '閘道器超時。',
};

然後,寫異常處理函式

/**
 * 異常處理程式
 */
const errorHandler = (error: { response: Response }): Response => {
  const { response } = error;
  if (response && response.status) {
    const errorText = codeMessage[response.status] || response.statusText;
    const { status, url } = response;

    notification.error({
      message: `請求錯誤 ${status}: ${url}`,
      description: errorText,
    });
  } else if (!response) {
    notification.error({
      description: '您的網路發生異常,無法連線伺服器',
      message: '網路異常',
    });
  }
  return response;
};

/**
 * 配置request請求時的預設引數
 */
const request = extend({
  errorHandler, // 預設錯誤處理
  credentials: 'include', // 預設請求是否帶上cookie
  // timeout: 60000, // 請求超時
});

首先第一個需求:對請求結果異常的統一處理。比如:token 失效時,應該統一彈框提示,並且跳回到登入頁。非成功的統一提示。直接拿到後端返回的資料而去掉外層的包裝。

request.interceptors.response.use(async (response) => {
  const data = await response.clone().json();
  // const currentInterface = getPureInterface(response.url); // 這個方法是為了得到純介面,然後可以適時的選擇跳過,或者做別的操作
  // token 失效
  if(data.code === 1014) {
    window.location.href = `${window.location.origin}/user/login`;
  }
  // 統一報錯資訊。需特殊跳過的介面可以在這裡跳過
  if(data.code === 1009) {
    // ant 引入的元件
    notification.error({
      message: '請求錯誤',
      description: data.message,
    })
  }
  return response;
})

比如後端介面不同型別需要的引數格式不同。

// get 請求,引數拼接在 url 後面。並且需要在 headers 裡面新增引數 token
const requestGet = (url: string, data?: object) => {
  return request.get(`${url}?${qs.stringify({ ...data, t: Date.now() })}`, {
    headers: {
      tokenId: getCookie("token"),
    }
  })
}

// post 請求,form 格式,每個請求都需要包含 token,accout 引數
const requestPost = (url: string, data?: object) => {
  return request.post(url, {
    method: 'POST',
    data: {
      ...data,
      tokenId: getCookie("token"),
      account: getCookie("account"),
    },
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      tokenId: getCookie("token"),
    }
  })
}

// post 請求,要求的入參卻是 json 格式
const requestPostJson = (url: string, data?: object) => {
  return request.post(url, {
    method: 'POST',
    data,
    headers: {
      'Content-Type': 'application/json',
      tokenId: getCookie("token"),
    },
  })
}
// 這是全域性的攔截,還可以寫區域性的攔截器

封裝完成之後,最後暴露出來即可使用

export default {
  get: requestGet,
  post: requestPost,
  json: requestPostJson
};

比如請求前的攔截

/**
 * 請求前攔截。比如新增資料或者,修改url
 */
request.interceptors.request.use( (url, options) => {
  // console.log('url=',url)
  // console.log('options', options)
  /**
   * 這裡的新增會在上面各自的請求之後執行,比如url 的拼接
   * 這裡可以根據 options 的引數決定要不要修改或者拼接不同的前後綴
   * options 包含 credentials、errorHandler、headers、method、params、
   */
  return {
    url: `xingquan${url}&author=guozheng`,
    options: {...options, interceptors: true}
  }
})

還有好多方便的用法,文件很詳細,使用到再補充。