react中请求接口的封装

Posted sidney前端攻略

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react中请求接口的封装相关的知识,希望对你有一定的参考价值。

1. 新建一个dva项目。使用antd 或者antd-mobile组件库。
 
   
   
 
  1. $ npm install dva-cli -g

  2. $ dva -v

  3. $ dva new dva-quickstart

  4. $ npm start

 
   
   
 
  1. $  npm  install antd babel-plugin-import --save

  2. 或者是

  3. $  npm  install antd-mobile babel-plugin-import --save

导入方式css

 
   
   
 
  1. {

  2.  "entry": "src/index.js",

  3.  "env": {

  4.    "development": {

  5.      "extraBabelPlugins": [

  6.        "dva-hmr",

  7.        "transform-runtime",

  8.        ["import", { "libraryName": "antd-mobile", "style": "css" }]

  9.      ]

  10.    },

  11.    "production": {

  12.      "extraBabelPlugins": [

  13.        "transform-runtime",

  14.        ["import", { "libraryName": "antd-mobile", "style": "css" }]

  15.      ]

  16.    }

  17.  }

  18. }

2. 在该项目的src中utils 创建名为request文件夹。
 
   
   
 
  1. $ cd  dva-quickstart

  2. $ cd  src

  3. $ cd utils

新建文件夹名为request,然后在request文件夹下面创建名为helpers的文件夹以及index.js 和 README.md , request.js 如图所示:

在helpers 下建三个js文件 combineURL.js , isAbsoluteURL.js , serialize.js

combineURL.js中 :

react中请求接口的封装

isAbsoluteURL.js中 :

react中请求接口的封装serialize.js中 :

3. 在utils下创建一个与request同级的lang.js

lang.js 如下:

 
   
   
 
  1. export const isPresent = (obj) => {

  2.  return typeof obj !== 'undefined' && obj !== null;

  3. };

  4. export const isBlank = (obj) => {

  5.  return typeof obj === 'undefined' || obj === null;

  6. };

  7. export const isBoolean = (obj) => {

  8.  return typeof obj === 'boolean';

  9. };

  10. export const isNumber = (obj) => {

  11.  return typeof obj === 'number';

  12. };

  13. export const isString = (obj) => {

  14.  return typeof obj === 'string';

  15. };

  16. export const isArray = (obj) => {

  17.  return Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Array]';

  18. };

  19. export const isDate = (obj) => {

  20.  return obj instanceof Date && !isNaN(obj.valueOf());

  21. };

  22. export const isFunction = (obj) => {

  23.  return typeof obj === 'function';

  24. };

  25. export const isJsObject = (obj) => {

  26.  return obj !== null && (isFunction(obj) || typeof obj === 'object');

  27. };

  28. export const isPromise = (obj) => {

  29.  return isPresent(obj) && isFunction(obj.then);

  30. };

  31. export const isEmpty = (obj) => {

  32.  if (isBlank(obj)) {

  33.    return true;

  34.  }

  35.  if (obj.length === 0) {

  36.    return true;

  37.  }

  38.  for (const key in obj) {

  39.    if (Object.prototype.hasOwnProperty.call(obj, key)) {

  40.      return false;

  41.    }

  42.  }

  43.  return true;

  44. };

  45. export const normalizeBlank = (obj) => {

  46.  return isBlank(obj) ? null : obj;

  47. };

  48. export const normalizeBool = (obj) => {

  49.  return isBlank(obj) ? false : obj;

  50. };

  51. export const stringify = (token) => {

  52.  if (isString(token)) {

  53.    return token;

  54.  }

  55.  if (isBlank(token)) {

  56.    return String(token);

  57.  }

  58.  const ret = token.toString();

  59.  const newLineIndex = ret.indexOf('\n');

  60.  return (newLineIndex === -1) ? ret : ret.substring(0, newLineIndex);

  61. };

  62. export class PromiseWrapper {

  63.  // Excutes promises one by one, e.g.

  64.  // const promise = () => new Promise(...)

  65.  // const promise2 = () => new Promise(...)

  66.  // sequentialize([ promise, promise2 ])

  67.  static sequentialize = promiseFactories => {

  68.    let chain = Promise.resolve();

  69.    promiseFactories.forEach(factory => {

  70.      chain = chain.then(factory);

  71.    });

  72.    return chain;

  73.  }

  74.  // Promise finally util similar to Q.finally

  75.  // e.g. finally(promise.then(...))

  76.  /* eslint-disable consistent-return */

  77.  static finally = (promise, cb) => promise.then(res => {

  78.    const otherPromise = cb();

  79.    if (typeof otherPromise.then === 'function') {

  80.      return otherPromise.then(() => res);

  81.    }

  82.  }, reason => {

  83.    const otherPromise = cb();

  84.    if (typeof otherPromise.then === 'function') {

  85.      return otherPromise.then(() => {

  86.        throw reason;

  87.      });

  88.    }

  89.    throw reason;

  90.  })

  91. }

  92. /* eslint-enable consistent-return */

  93. export class StringWrapper {

  94.  static equals = (s1, s2) => s1 === s2;

  95.  static contains = (s, substr) => s.indexOf(substr) !== -1;

  96.  static compare = (a, b) => {

  97.    if (a < b) {

  98.      return -1;

  99.    } else if (a > b) {

  100.      return 1;

  101.    }

  102.    return 0;

  103.  }

  104. }

  105. /* eslint-disable max-params */

  106. export class DateWrapper {

  107.  static create(

  108.    year,

  109.    month = 1,

  110.    day = 1,

  111.    hour = 0,

  112.    minutes = 0,

  113.    seconds = 0,

  114.    milliseconds = 0

  115.  ) {

  116.    return new Date(year, month - 1, day, hour, minutes, seconds, milliseconds);

  117.  }

  118.  static fromISOString(str) {

  119.    return new Date(str);

  120.  }

  121.  static fromMillis(ms) {

  122.    return new Date(ms);

  123.  }

  124.  static toMillis(date) {

  125.    return date.getTime();

  126.  }

  127.  static now() {

  128.    return Date.now() || new Date();

  129.  }

  130.  static toJson(date) {

  131.    return date.toJSON();

  132.  }

  133. }

  134. /* eslint-enable max-params */

这个是dva自动生成的request.js 把这个文件换下名字requests.js,它与lang.js同级。

4. 打开在request文件下request.js,进行编辑:

request.js

 
   
   
 
  1. import fetch from 'dva/fetch';

  2. import { isEmpty } from '../lang';

  3. import serialize from './helpers/serialize';

  4. import combineURL from './helpers/combineURL';

  5. import isAbsoluteURL from './helpers/isAbsoluteURL';

  6. import { apiBaseUrl } from '../../config';

  7. import { Toast } from 'antd-mobile';

  8. const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

  9. const timeout = (p, ms = 30 * 1000) =>

  10.  Promise.race([

  11.    p,

  12.    wait(ms).then(() => {

  13.      const error = new Error(`Connection timed out after ${ms} ms`);

  14.      error.statusCode = 408;

  15.      throw error;

  16.    }),

  17.  ]);

  18. // Request factory

  19. function request(url, options, method) {

  20.  const { endpoint, ...rest } = interceptRequest(url, options, method);

  21.  const xhr = fetch(endpoint, rest).then(interceptResponse);

  22.  return timeout(xhr, request.defaults.timeout).catch((error) => {

  23.    // return Promise.reject(error);

  24.  });

  25. }

  26. request.defaults = {

  27.  baseURL: apiBaseUrl,

  28.  timeout: 10 * 5000,

  29.  headers: {

  30.    Accept: 'application/json',

  31.  },

  32. };

  33. // Headers factory

  34. const createHeaders = () => {

  35.  const headers = {

  36.    ...request.defaults.headers,

  37.  };

  38.  // const auth = JSON.parse(localStorage.getItem('auth'+sessionStorage.getItem("hid")));

  39.  // const token = sessionStorage.getItem('token'); // <Michael> 登录location获取到的token存放l

  40.  // if (auth) {

  41.  //   // Toast.info(`请稍等: ${token}`, 2);

  42.  //   // Toast.loading('');

  43.  //   headers.Authorization = auth.Token;

  44.  // } else if (token) {

  45.  //   // <Michael>;

  46.  //   // Toast.info(`请稍等: ${token}`, 2);

  47.  //   // Toast.loading('');

  48.  //   headers.Authorization = token;

  49.  // }

  50.  headers.Authorization = "app";

  51.  return headers;

  52. };

  53. // Request interceptor

  54. function interceptRequest(url, options, method) {

  55.  let endpoint;

  56.  if (isAbsoluteURL(url)) {

  57.    endpoint = url;

  58.  } else {

  59.    endpoint = combineURL(request.defaults.baseURL, url);

  60.  }

  61.  let data = {

  62.    method,

  63.    endpoint,

  64.    headers: createHeaders(),

  65.  };

  66.  if (!isEmpty(options)) {

  67.    data = {

  68.      ...data,

  69.      ...options,

  70.    };

  71.    if (options.json) {

  72.      data.headers['Content-Type'] = 'application/json;charset=utf-8';

  73.      data.body = JSON.stringify(options.json);

  74.    }

  75.    if (options.form) {

  76.      data.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';

  77.      data.body = serialize(options.form);

  78.    }

  79.    if (options.body) {

  80.      data.body = options.body;

  81.      const auth = JSON.parse(localStorage.getItem('auth'+sessionStorage.getItem("hid")));

  82.      if (auth) {

  83.        if (auth && options.body instanceof FormData && !options.body.hasPatientid) {

  84.          // options.body.append('patientid', auth.Patientid);

  85.        }

  86.      }

  87.    }

  88.    if (options.params) {

  89.      endpoint += `?${serialize(options.params)}`;

  90.      data.endpoint = endpoint;

  91.    }

  92.  }

  93.  return data;

  94. }

  95. // Response interceptor

  96. /* eslint-disable consistent-return */

  97. function interceptResponse(response) {

  98.  return new Promise((resolve, reject) => {

  99.    const emptyCodes = [204, 205];

  100.    // Don't attempt to parse 204 & 205

  101.    if (emptyCodes.indexOf(response.status) !== -1) {

  102.      return resolve(response.ok);

  103.    }

  104.    if (response.ok) {

  105.      const contentType = response.headers.get('Content-Type');

  106.      if (contentType.includes('application/json')) {

  107.        resolve(response.json());

  108.      }

  109.      resolve(response);

  110.    }

  111.    if (response.status === 401) {

  112.      // return Toast.fail('认证信息已过期,请重新登录', 2, () => {

  113.      // return Toast.fail('请重新登录', 2, () => {

  114.        localStorage.removeItem('auth'+sessionStorage.getItem("hid"));

  115.        // sessionStorage.removeItem('token');

  116.        location.reload();

  117.        // TODO:跳转登录路由

  118.      // });

  119.    }

  120.    const error = new Error(response.statusText);

  121.    try {

  122.      response.clone().json().then((result) => {

  123.        error.body = result;

  124.        error.response = response;

  125.        reject(error);

  126.      });

  127.    } catch (e) {

  128.      error.response = response;

  129.      reject(error);

  130.    }

  131.  });

  132. }

  133. /* eslint-enable consistent-return */

  134. // suger

  135. request.get = (url, options) => request(url, options, 'GET');

  136. request.head = (url, options) => request(url, options, 'HEAD');

  137. request.options = (url, options) => request(url, options, 'OPTIONS');

  138. request.post = (url, options) => request(url, options, 'POST');

  139. request.put = (url, options) => request(url, options, 'PUT');

  140. request.delete = (url, options) => request(url, options, 'DELETE');

  141. request.del = request.delete;

  142. export default request;

5. 这样你就可以在今后的项目正常使用按照以下步骤
 
   
   
 
  1. module.exports = {

  2.    apiBaseUrl: "http://172.118.100.50/api/",

  3. };

之后再services文件下就可以这样去下啦:

 
   
   
 
  1. import request from '../utils/request/request';

  2. export function queryScaleMenu(start, limit) {

  3.   const body = new FormData();

  4.    body.append('start',start);

  5.    body.append('limit', limit);

  6.    return request.post('news/menu/query', { body });

  7. }


以上是关于react中请求接口的封装的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装

java中封装,继承,多态,接口学习总结

react组件初始化接口请求有多个异步依赖参数

react封装基于axios的API请求