axios请求

355 阅读1分钟

axios基本使用

const instance = axios.create({
    baseURL: `https://xx`,
})
// 1.
instance.get('/project/getList', {
    params: {
        
    }
})
.then(response => {
    console.log(response.data);
})
.catch(error => {
    console.error(error);
});
// 2.
instance({
    method: 'get',
    url: '/project/getList',
    params: {
        
    }
})
.then(response => {
    console.log(response.data);
})
.catch(error => {
    console.error(error);
});

前端检查登录态,进行请求拦截

instance.interceptors.request.use(config => {
   const { isLogin } = checkLogin();
   if (!isLogin) {
     login();
   }
   return config;
});

后端检查登录态,前端进行响应拦截

如果后端校验登录态,那么前端需要在登录态失效的时候,进行拦截,并跳转到统一登录地址,具体实现如下:

import axios from 'axios';
import { message } from 'ant-design-vue';

const instance = axios.create({
    baseURL: `https://${location.host}/your-address`,
});

instance.interceptors.response.use(
    res => {
        const { iRet, data, sMsg, status } = res.data;
        if (iRet === 0 || status === 200) {
            return { data, sMsg };
        } else if (iRet === -99) {
            // 登录态失效,重新登录
            const current_key = 'key';
            const checkUrl = `callbackURL?lastUrl=${encodeURI(
                location.href,
            )}`;
            window.location.href = `https://passport.com&key=${current_key}&url=${checkUrl}`;
        } else {
            console.log(`接口拦截 - ${iRet}`, sMsg);
            message.error(sMsg);
            return Promise.reject(sMsg);
        }
    },
    err => {
        // 非 2xx 范围内的状态码都会触发该函数。
        console.log('接口拦截 - 非2xx状态码', err);
        return Promise.reject(err);
    },
);
// 方法1:可对每个请求统一处理
export const fetch = config => {
    return instance(config);
};
// 方法2:更简单
export default instance
// 方法1
import { fetch } from './fetch';
export const getList = params => {
    return fetch({
        method: 'get',
        url: '/project/getList',
        params,
    });
};
// 方法2
import instance from './fetch';
export const getList = params => {
    return instance({
        method: 'get',
        url: '/project/getList',
        params,
    });
};

case1:返回数据格式

描述 当申请接口时,后端返回的是javascript字符串,如下:

var result = "{"ret":1,"msg":"\u6570\u636e\u83b7\u53d6\u6210\u529f","data":"","script.."

第一种方式:请求URL加上参数

请求URL加上format=json参数或者是type=json通常是API设计者提供的一种方式,用于指定返回数据的格式。当你在请求URL中添加这个参数时,API服务器会根据这个参数返回JSON格式的数据。

第二种方式:设置Accept头部

可以在创建axios实例时通过设置headers属性来指定Accept头部信息。

const instance = axios.create({
    baseURL: `https://a.com/`,
    withCredentials: true,
    headers: {
        'Accept': 'application/json'
    }
});

第三种方式:匹配js字符串

如果后端接口没有设计为根据请求头中的Accept字段或者请求参数中的format来返回不同格式的数据,那么即使在前端请求中指定Accept: application/json或者添加format=json参数,也无法强制后端返回JSON格式的数据。后端服务需要明确支持这种内容协商机制,才能根据客户端的请求返回不同格式的响应。

//假设responseText是API返回的响应文本
let responseText = 'var result = {"key": "value"};';

// 使用正则表达式匹配JSON对象
let jsonMatch = responseText.match(/var result = (.*);/);
if (jsonMatch && jsonMatch[1]) {
  // 尝试解析匹配到的字符串为JSON对象
  try {
    let jsonData = JSON.parse(jsonMatch[1]);
    console.log(jsonData); // 这里是解析后的JSON对象
  } catch (e) {
    console.error('解析JSON失败:', e);
  }
}

case2: 发送数据格式

描述

在开发中,遇到post请求数据除了请求载荷,还有表单数据,导致前端发请求无法得到正确回应:

image.png

当采用post发送请求时,形如:

import axios from 'axios';
// 创建axios实例
const instance = axios.create({
  baseURL: 'http://your-api-base-url.com', // 你的API基础URL
  timeout: 1000, // 请求超时时间
  // 其他配置...
});
// 发送GET请求
instance({
  method: 'get',
  url: '/your-endpoint',
}).then(response => {
  console.log(response.data); // 处理响应数据
}).catch(error => {
  console.error(error); // 处理错误情况
});

// 发送POST请求
instance({
  method: 'post',
  url: '/your-endpoint',
  data: {
    key: 'value', // 这里放置你要发送的数据
  }
}).then(response => {
  console.log(response.data); // 处理响应数据
}).catch(error => {
  console.error(error); // 处理错误情况
});

第一种方式:使用formData创造对象

  • 当传入data为对象,axios会自动转化为JSON字符串(显示为请求载荷);
  • 当传入data为FormData对象,axios会自动转化为表单数据(显示为表单数据)
let formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
axios.post('/your-endpoint', formData);

// 如果是请求载荷
let payload = {
    key1: 'value1',
    key2: 'value2'
};
axios.post('/your-endpoint', payload);

第二种方式:设置headers为{'Content-Type': 'application/x-www-form-urlencoded'}

instance({
    method: 'post',
    url: '/module/other/index.php?c=ruleQual&a=modifyQual&type=json',
    data,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then().catch()

另外,一个请求可以既可以有data 又可以有params:

 export const update = ({params, data}) => {
    return instance({
        method: 'post',
        url: '/a=update&type=json&',
        params,
        data,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    });
 };

axios捕获错误

第一种方式:async/await + try/catch 捕获同步错误

async create() {
    let self = this;
    try {
        const res = await axios.post(`https://${self.apiHost}/${self.testPath}/operation/create`, 
            {
                params,
            },
            {
                withCredentials: true
            }
        )
        if (res.data.iRet == 0) {
            console.log('success')
        } 
    } catch(err) {
        console.log('err', err);
    }
}

try/catch捕获同步错误:

try {
 console.log(res);
}
catch (error) {
   // 捕获到错误,并在控制台输出错误信息
   console.error('捕获到同步错误:', error.message);
}

第二种方式:.then 捕获异步错误

const api = axios.create({
    baseURL: `https://${apiHost}`,
    withCredentials: true,
});

const create = data => {
    return api({
        method: "post",
        url: `/${testPath}/operation/create`,
        data,
    });
    
create({
 params      
})
    .then(() => {
        console.log('success')
    })
    .catch(err => {
        console.log("err", err);

    });

Cookie

Cookie 设置

cookie 通常由服务器通过 HTTP 响应头 Set-Cookie 发送给客户端,然后客户端会存储这些cookie信息。在后续的请求中,浏览器会自动将这些cookie信息附加到请求头中,发送给服务器。

跨域请求带 Cookie

当涉及到跨域请求时,默认情况下,浏览器出于安全考虑不会发送cookie。但是,如果你希望在跨域请求中包含cookie,你需要在前端的请求中设置 withCredentials 为 true。同时,服务器也需要设置响应头 Access-Control-Allow-Credentials 为 true,并且 Access-Control-Allow-Origin 不能设置为 *,它必须指定为请求页面的源。

跨域

www.cnblogs.com/mochenxiya/…

这里所说的跨域问题,只能说是绕过浏览器的安全策略。

跨域请求由客户端发出后,会带有origin请求头,返回时候如果带有Access-Control-Allow-Origin字段,那么预检请求通过了,后续发送同一api的请求,就不再需要预检请求。当正常发送get或者post请求,返回的请求头中仍然带有Access-Control-Allow-Origin字段,如果没有该字段,或者该字段的值不允许当前源访问,浏览器将不会返回响应内容给JavaScript代码,而是在控制台中报出一个跨域错误。并且下一次访问该api时重新发送预检请求。如果预检请求没通过,那么浏览器端会直接拦截客户端发出的同api请求。

对于简单请求(GET、POST和一些HEAD请求),浏览器直接发送请求,但是响应必须包含Access-Control-Allow-Origin头信息,否则浏览器同样会阻止响应。

CORS

1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置

【前端设置】根据withCredentials字段判断是否带有cookie

Nginx反向代理

为后端返回的请求设置了Access-Control-Allow-Origin,这样一来,在前端的开发服务器中就不需要再配置跨域。

Nginx反向代理在线上环境下非常有用,主要是因为它提供了一系列的功能和优势,这些在本地开发环境中通常不是必需的,或者可以通过其他简单的方式实现。例如:负载均衡

server {
    listen 80;
    server_name example.com;

    location / {
        root /path/to/your/app;
        index index.html;
    }

    location /api {
        proxy_pass http://backend-api;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        add_header 'Access-Control-Allow-Origin' '*';
    }
}

Webpack本地代理和whistle

Whistle 是一种开发环境代理方案。它是一个基于Node.js的跨平台web调试工具,可以用来拦截和修改HTTP、HTTPS、WebSocket等网络请求。Whistle 提供了丰富的功能,比如请求转发、响应模拟、性能优化、安全检查等,非常适合前端开发者和测试工程师使用。

与Webpack的本地代理功能相比,Whistle 提供了更为强大和灵活的网络请求处理能力。Webpack的代理主要是在开发环境中解决前后端分离时的跨域问题,通常配置在webpack.config.js文件的devServer.proxy选项中。而Whistle 不仅可以用于本地开发环境,还可以用于测试环境和生产环境的网络请求调试和优化。