关于前端:react开发利器-之-fetch请求封装

41次阅读

共计 6039 个字符,预计需要花费 16 分钟才能阅读完成。

Fetch

Fetch API 提供了一个 JavaScript 接口,用于拜访和操纵 HTTP 管道的一些具体局部,例如申请和响应。

它还提供了一个全局 fetch() 办法,该办法提供了一种简略,正当的形式来跨网络异步获取资源。

这种性能以前是应用 XMLHttpRequest 实现的。

Fetch 提供了一个更现实的代替计划,能够很容易地被其余技术应用,例如 Service Workers。

Fetch 还提供了 专门的逻辑空间来定义其余与 HTTP 相干的概念,例如 CORS 和 HTTP 的扩大。

请留神,fetch 标准 jQuery.ajax() 次要有以下的不同:

  • 当接管到一个代表谬误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject,即便响应的 HTTP 状态码是 404 或 500。相同,它会 将 Promise 状态标记为 resolve(如果响应的 HTTP 状态码不在 200 – 299 的范畴内,则设置 resolve 返回值的 ok 属性为 false),仅当 网络故障 时或 申请被阻止 时,才会标记为 reject
  • fetch 不会发送跨域 cookie,除非你应用了 credentials 的初始化选项

一个根本的 fetch 申请设置起来很简略。看看上面的代码:

fetch('http://example.com/movies.json')
  .then(response => response.json())
  .then(data => console.log(data));

参考 fetch(),查看所有可选的配置和更多形容。

// Example POST method implementation:
async function postData(url = '', data = {}) {
  // Default options are marked with *
  const response = await fetch(url, {
    method: 'POST', // *GET, POST, PUT, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin', // include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json'
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    redirect: 'follow', // manual, *follow, error
    referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
    body: JSON.stringify(data) // body data type must match "Content-Type" header
  });
  return response.json(); // parses JSON response into native JavaScript objects}

postData('https://example.com/answer', { answer: 42})
  .then(data => {console.log(data); // JSON data parsed by `data.json()` call});

留神:mode: “no-cors” 仅容许应用一组无限的 HTTP 申请头:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type 容许应用的值为:application/x-www-form-urlencodedmultipart/form-datatext/plain

MDN 地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Us…

qs 简介

一个带有一些附加 安全性 查问字符串解析 字符串化 库。

次要维护者:Jordan Harband

最后创建者和维护者:TJ Holowaychuk

npmjs 仓库地址:https://www.npmjs.com/package/qs

react 应用 qs

装置

npm install qs

import qs from'qs'

qu.stringify()和 qs.parse()

  • qu.stringify() : 将 对象序列化成 url 的模式 ;以& 进行拼接
  • qs.parse(): 将 url 解析成对象模式;

1、qs.parse() 将 URL 解析成对象的模式

import  Qs from 'qs';
let url = 'method=query_sql_dataset_d<a style="color:transparent"> 起源 gao*daima.com 搞 @代 #码网 </a>ata&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0';
Qs.parse(url);
console.log(Qs.parse(url));

输入后果

{
    method:'query_sql_dataset_data',
    projectId:'85',
    appToken:'7d22e38e-5717-11e7-907b-a6006ad3dba0'
}

2、qs.stringify()将对象序列化成 URL 的模式,以 & 进行拼接(可用于发送查问条件)

import  Qs from 'qs';
let obj= {
     method: "query_sql_dataset_data",
     projectId: "85",
     appToken: "7d22e38e-5717-11e7-907b-a6006ad3dba0",
     datasetId: "12564701"
   };
Qs.stringify(obj);
console.log(Qs.stringify(obj));

输入的是:

method=query_sql_dataset_data&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0&datasetId=%12564701

JSON.stringify(param) VS Qs.stringify(param)

JSON 中同样存在 stringify办法,然而和 Qs.stringify 之间的区别是很显著的

// JSON.stringify(param) 
{"uid":"cs11","pwd":"000000als","username":"cs11","password":"000000als"}

// Qs.stringify(param)
uid=cs11&pwd=000000als&username=cs11&password=000000als

封装 fetch

为什么封装 Fetch 申请

  • 申请的中央代码更少。
  • 公共的谬误对立一个中央增加即可。
  • 申请定制的谬误还是申请本人也能够解决。
  • 扩展性好,增加性能只须要改一个中央。

总结起来一句话:简略,好用

封装 Fetch 申请(次要文件)

“./fetchUtil”

import qs from 'qs';
import {message} from 'antd';

const {stringify, parse} = qs;

const checkStatus = res => {if (200 >= res.status < 300) {return res;}
  message.error(` 网络申请失败,${res.status}`);
  const error = new Error(res.statusText);
  error.response = error;
  throw error;
};

/**
 *  捕捉胜利登录过期状态码等
 * @param res
 * @returns {*}
 */
const judgeOkState = async res => {const cloneRes = await res.clone().json(); 
  
  //TODO: 能够在这里管控全局申请
  if (!!cloneRes.code && cloneRes.code !== 200) {message.error(`11${cloneRes.msg}${cloneRes.code}`);
  }
  return res;
};

/**
 * 捕捉失败
 * @param error
 */
const handleError = error => {if (error instanceof TypeError) {message.error(` 网络申请失败啦!${error}`);
  }
  return {   // 避免页面解体,因为每个接口都有判断 res.code 以及 data
    code: -1,
    data: false,
  };
};

class http {
  /**
   * 动态的 fetch 申请通用办法
   * @param url
   * @param options
   * @returns {Promise<unknown>}
   */
  static async staticFetch(url = '', options = {}) {

    const defaultOptions = {
      /* 容许携带 cookies*/
      credentials: 'include',
      /* 容许跨域 **/
      mode: 'cors',
      headers: {
        token: null,
        Authorization: null,
        // 当申请办法是 POST,如果不指定 content-type 是其余类型的话,默认为如下,要求参数传递款式为 key1=value1&key2=value2,但理论场景以 json 为多
        // 'content-type': 'application/x-www-form-urlencoded',
      },
    };
    if (options.method === 'POST' || 'PUT') {defaultOptions.headers['Content-Type'] = 'application/json; charset=utf-8';
    }
    const newOptions = {...defaultOptions, ...options};
    console.log('newOptions', newOptions);
    return fetch(url, newOptions)
      .then(checkStatus)
      .then(judgeOkState)
      .then(res => res.json())
      .catch(handleError);
  }

  /**
   *post 申请形式
   * @param url
   * @returns {Promise<unknown>}
   */
  post(url, params = {}, option = {}) {const options = Object.assign({ method: 'POST'}, option);
    // 个别咱们罕用场景用的是 json,所以须要在 headers 加 Content-Type 类型
    options.body = JSON.stringify(params);

    // 能够是上传键值对模式,也能够是文件,应用 append 发明键值对数据
    if (options.type === 'FormData' && options.body !== 'undefined') {let params = new FormData();
      for (let key of Object.keys(options.body)) {params.append(key, options.body[key]);
      }
      options.body = params;
    }
    return http.staticFetch(url, options); // 类的静态方法只能通过类自身调用
  }

  /**
   * put 办法
   * @param url
   * @returns {Promise<unknown>}
   */
  put(url, params = {}, option = {}) {const options = Object.assign({ method: 'PUT'}, option);
    options.body = JSON.stringify(params);
    return http.staticFetch(url, options); // 类的静态方法只能通过类自身调用
  }

  /**
   * get 申请形式
   * @param url
   * @param option
   */
  get(url, option = {}) {const options = Object.assign({ method: 'GET'}, option);
    return http.staticFetch(url, options);
  }
}

const requestFun = new http(); //new 生成实例
export const {post, get, put} = requestFun;
export default requestFun;

定义接口文件,导出 fetch

utils/api

import requestFun from "./fetchUtil"; // 引入
import qs from "qs";

const {stringify} = qs;
const {post, get} = requestFun;

//get 形式
export async function fetchData1(params) {return get(`/api/bbb?${stringify(params)}`);
}

//post 形式
export async function fetchData2(params) {return post(`/api/aaa`, params);
}
 
export async function fetchGetComments(params) {return get(`http://localhost:8001/comments`, params);
}

组件内应用

home.js

import {fetchGetComments} from '../../utils/api'

// 获取数据
const loadData = async ()=> {const commentData = await fetchGetComments();
    console.log('commentData')
    console.log(commentData) 
}

延申问题

如果要扩大 fetch 的 delete 和 patch,该如何做?

如果自定义 header 的话,该如何做?

如果 post 后端须要 formdata 构造数据又该如何做?

感兴趣的小伙伴,能够自行脑补一下。

参考文档

  • https://www.jianshu.com/p/a6573cd68ae6

正文完
 0