跳至主要內容

8.7 网络请求 🎉

刘春龙...大约 6 分钟RRACTWEB前端reactreact路由

8.7 网络请求 🎉

Fetch 💎

Fetch 是一种通信协议,用于客户端和服务器之间的数据传输。它允许浏览器从服务器异步请求数据,而无需刷新整个页面

Fetch API 是一个基于 Promise 的 JavaScript API,用于使用 Fetch 协议进行网络请求。Fetch API 提供了一种更简洁的方式来处理HTTP请求,并提供了比 XMLHttpRequest 更强大和灵活的功能。Fetch API 还允许开发人员轻松地使用现代 JavaScript 语言特性,如箭头函数和 async/await

Fetch API 支持多种数据格式,包括 JSON、二进制数据、FormData 等。它还支持 CORS(跨源资源共享)以及请求和响应拦截

总之,Fetch API 是一种现代的、灵活的、易于使用的方式来进行网络请求,并且它已经被大多数现代浏览器所支持

Fetch API 的基本用法是使用 fetch() 函数来发起HTTP请求,并返回一个 Promise 对象。该 Promise 对象会在请求完成后解析响应数据,并在请求成功时返回一个 Response 对象,或在请求失败时返回一个 rejected 状态的 Promise 对象

import React, { useEffect } from 'react';
export default function App() {
  useEffect(() => {
    fetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")
      .then(response => {
        return response.json();
      })
      .then(data => {
        console.log(data)
      })
      .catch(error => {
        console.log(error)
      })
  }, [])
  return (
    <div>
      <p>11</p>
    </div>
  )
}

GET请求 👻

Fetch 默认发送 GET 请求,属于快捷方式。当然我们也可以指定具体的请求方式

fetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php", {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
   }
}).then(res => res.json()).then(data => {
  console.log(data)
}).catch(error => {
  console.log(error)
})

可以通过在 fetch() 函数的第二个参数中指定请求选项来实现这些方法,例如请求头、参数、模式、缓存等

//传参
fetch("http://iwenwiki.com/api/blueberrypai/getSongInfo.php?song=mo", {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
   }
}).then(res => res.json()).then(data => {
  console.log(data)
}).catch(error => {
  console.log(error)
})

POST请求 👻

除了基本的 GET 请求外,Fetch API 还支持其他HTTP方法,如 POST、PUT 和 DELETE。可以通过在 fetch() 函数的第二个参数中指定请求选项来实现这些方法,例如请求头、请求体、模式、缓存等

fetch("http://iwenwiki.com/api/blueberrypai/login.php", {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
   },
  body:"user_id=iwen@qq.com&password=iwen123&verification_code=crfvw"
}).then(res => res.json()).then(data => {
  console.log(data)
}).catch(error => {
  console.log(error)
})

将参数通过对象方式传递

我们可以借助 querystring 实现参数的格式转换

npm install --save querystring
import qs from "querystring"


fetch("http://iwenwiki.com/api/blueberrypai/login.php", {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
   },
  body: qs.stringify({
    user_id: "iwen@qq.com",
    password: "iwen123",
    verification_code: "crfvw"
   })
}).then(res => res.json()).then(data => {
  console.log(data)
}).catch(error => {
  console.log(error)
})

Fetch await 语法改写 👻

fetch() 使用 Promise,不使用回调函数,因此大大简化了写法,写起来更简洁

Promise 可以使用 await 语法改写,使得语义更清晰

// 定义网络请求函数
const fetchGET = async (url) =>{
  const response = await fetch(url)
  const result = await response.json()
  return result
}
// 获取网络请求数据
const result = fetchGET("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")
result.then(res =>{
  console.log(res)
})

Fetch取消请求 👻

fetch()请求发送以后,如果中途想要取消,需要使用AbortController对象

controller.abort()方法用于发出取消信号

let controller = new AbortController();
fetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php", {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
   },
  signal:controller.signal
}).then(res => res.json()).then(data => {
  console.log(data)
}).catch(error => {
  console.log(error)
})
controller.abort(); // 取消

在一定时间内取消网路请求

let controller = new AbortController();
setTimeout(() => controller.abort(), 10);
fetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php", {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
   },
  signal:controller.signal
}).then(res => res.json()).then(data => {
  console.log(data)
}).catch(error => {
  console.log(error)
})

React跨域配置 💎


在开发模式下,如果客户端所在服务器跟后台服务器的地址或者端口不一致,则会出现跨域的问题

  • 方式1:使用Proxy解决跨域
    在package.json中设置Proxy属性:
"proxy":"http://localhost:3030"

设置代理后,则发送的api请求会被代理服务器转发到 localhost:3030

提示

proxy代理仅在开发中有效。

在生产环境下,这个代理无效

  • 方式2:使用http-proxy-middleware
    安装http-proxy-middleware
npm install http-proxy-middleware --save-dev

创建src/setupProxy.js文件(名字必须是这个名字,连后缀都不能变)

const { createProxyMiddleware } = require("http-proxy-middleware")
module.exports = function (app) {
    app.use("/api", createProxyMiddleware({
        target: "http://localhost:3005",
        changeOrigin: true,
        pathRewrite: {
            '^/api': ''
        }
    }))
    //可以代理多个
    // app.use("/api1", createProxyMiddleware({
    //     target: "http://localhost:3005",
    //     changeOrigin: true,
    //     pathRewrite: {
    //         '^/api': ''
    //     }
    // }))
}

Axios 💎

Axios 是一个基于 promise 的网络请求库,可以用于浏览器和 node.js

特性

  • 从浏览器创建 XMLHttpRequests
  • 从 node.js 创建 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF

参考地址: https://www.kancloud.cn/yunye/axios/234845open in new window

Axios 和 Fetch 的区别

  • Axios 支持更广泛的浏览器和环境,包括浏览器、Node.js 等;而 Fetch 只能在现代浏览器中使用,需要额外的 polyfill 才能在旧版浏览器中使用
  • Axios 可以自动地将响应数据转换为 JSON 格式,而 Fetch 不会自动转换,需要手动调用 response.json() 方法
  • Axios 支持请求和响应的拦截器(interceptors),可以在请求发送前或响应返回后进行一些操作,例如添加公共请求头、响应异常处理等;而 Fetch 不支持拦截器
  • Axios 支持取消请求,可以在请求还未返回时取消请求;而 Fetch 不支持取消请求
  • Axios 在处理错误时更加友好,返回的错误信息更加详细和有用;而 Fetch 的错误信息相对较少

安装axios

npm instal axios --save

基本用例

axios("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php").then(res =>{
    console.log(res.data)
}).catch(error =>{
    console.log(error)
})

GET请求 👻

执行 GET 请求,Axios提供可快捷方案

axios.get('http://iwenwiki.com/api/blueberrypai/getIndexBanner.php').then((response) => {
  console.log(response.data);
}).catch(function (error) {
  console.log(error);
});

GET传递参数

axios.get('http://iwenwiki.com/api/blueberrypai/getSongInfo.php?song=mo').then((response) => {
  console.log(response.data);
}).catch(function (error) {
  console.log(error);
});

增加配置信息,用对象方式传递参数

axios.get('http://iwenwiki.com/api/blueberrypai/getSongInfo.php', {
  params: {
    song: "mo"
   }
}).then((response) => {
  console.log(response.data);
}).catch(function (error) {
  console.log(error);
});

POST请求 👻

执行 POST 请求,Axios提供可快捷方案

Axios POST 接收的网络请求参数需要进行格式转化

需求的格式 username=iwen

npm install --save querystring
import qs from "querystring"
axios.post("http://iwenwiki.com/api/blueberrypai/login.php", qs.stringify({
  user_id: "iwen@qq.com",
  password: "iwen123",
  verification_code: "crfvw"
})).then(res =>{
  console.log(res.data)
}).catch(error =>{
  console.log(error)
})

并发请求 👻

在真实场景中,有可能会需要一次性获取多个网络请求的结果

处理并发请求的助手函数

  • axios.all(iterable)
  • axios.spread(callback)
function getBanner(){
  return axios.get("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")
}

function getChating(){
  return axios.get("http://iwenwiki.com/api/blueberrypai/getIndexChating.php")
}

const clickAllHandler = () =>{
  axios.all([getBanner(),getChating()])
     .then(axios.spread((banner,chating) =>{  // 两个参数分别代表两次网络请求的结果
    console.log(banner.data,chating.data)
   }))
}

Axios 封装 👻

封装 axios 之后,在使用上会更优雅,我们知道面向对象编程(OOP)遵循,低耦合高内聚。我们把网络请求放在一起更利于后期维护

新建/src/api/request.tsx

import axios from "axios"
const errorHandle = (status: any, info: any) => {
    switch (status) {
        case 400:
            console.log("语义错误");
            break;
        case 401:
            console.log("服务器认证失败");
            break;
        case 403:
            console.log("服务器请求拒绝执行");
            break;
        case 404:
            console.log("请检查网路请求地址");
            break;
        case 500:
            console.log("服务器发生意外");
            break;
        case 502:
            console.log("服务器无响应");
            break;
        default:
            console.log(info);
            break;
    }
}
const instance = axios.create({
    timeout: 50000,
})
const headers = {
    "Content-Type": 'application/json',
    "Authorization": 'lcl',
}
// 拦截器:请求拦截
instance.interceptors.request.use(
    (config) => {
        config.headers = headers
        return config
    },
    (error) => Promise.reject(error)
)
// 拦截器:响应拦截
instance.interceptors.response.use(
    (response) => response.status === 200 ? Promise.resolve(response) : Promise.reject(response),
    (error) => {
        const { response } = error;
        if (response) {
            errorHandle(response.status, response.info)
        } else {
            console.log("网络请求被中断了");
        }
    }
)
export default instance

新建/src/api/index.tsx

import axios from "./request"
const base = {
    baseUrl: "/api",   //代理地址在setupProxy.js文件里
    select: "/list",
    selectSwiper: "/selectSwiper",
}
const api = {
    select(params: any) {    //post请求
        return axios.post(base.baseUrl + base.select, { params })
    },
    selectSwiper(params: any) {    //get请求
        return axios.post(base.baseUrl + base.selectSwiper, params)
    },
}
export default api

发送请求

import api from "./api/index"
api.selectSwiper({
    name: "jikezc",
}).then((res: any) => {
    console.log(res.data);
})
上次编辑于:
贡献者: 刘春龙
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.7