安全性角度
核心分为「直接访问公开服务」和「通过后端中转访问私密服务」两类
| 场景类型 | 适用场景 | 安全等级 | 关键说明 |
|---|---|---|---|
| 直接访问公开服务 | 无需敏感凭证、公开可访问的API(如天气API、公开资讯API) | 中 | 直接通过前端请求,无需后端介入 |
| 通过后端中转访问私密服务 | 需要敏感凭证(如翻译API的appid/secretKey)、需权限校验的服务 | 高 | 前端仅传递业务参数,敏感逻辑由后端处理 |
前端访问服务的核心是基于HTTP/HTTPS协议(或WebSocket/SSE等特殊协议)实现数据交互,下面按「原生无依赖」「第三方库」「跨端/特殊场景」「实时通信」四大类展开,每类包含详细用法、示例、优缺点及适用场景,覆盖绝大多数前端开发需求。
一、第一类:原生无依赖请求方式(无需安装第三方包)
这类方式依赖浏览器/运行环境内置API,无需额外引入依赖,兼容性各有差异。
1. XMLHttpRequest(传统原生方式,兼容所有浏览器)
这是最早的前端网络请求API,兼容包括IE在内的所有浏览器,现在虽被fetch/axios替代,但在老旧项目或特殊兼容场景仍有使用。
适用场景
- 兼容IE6+等老旧浏览器;
- 需精细控制请求流程(如上传进度监控)。
完整代码示例(百度翻译中转请求)
javascript
/**
* 原生XMLHttpRequest访问后端中转接口
* @param {string} query 待翻译文本
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<Object>} 翻译结果
*/
export function baiduTranslateByXHR(query, from = 'auto', to = 'en') {
return new Promise((resolve, reject) => {
// 前置参数校验
if (!query?.trim()) {
reject(new Error('请传入有效的待翻译文本'));
return;
}
// 1. 创建XHR实例
const xhr = new XMLHttpRequest();
// 2. 配置请求(方法、地址、是否异步)
const url = 'http://localhost:3000/api/translate/baidu';
xhr.open('POST', url, true); // true表示异步请求
// 3. 设置请求头(传递JSON需配置Content-Type)
xhr.setRequestHeader('Content-Type', 'application/json');
// 4. 配置超时时间(单位:毫秒)
xhr.timeout = 8000;
// 5. 监控请求状态变化
xhr.onreadystatechange = function () {
// readyState=4 表示请求完成(响应已接收)
if (xhr.readyState === 4) {
// status=200 表示请求成功
if (xhr.status >= 200 && xhr.status < 300) {
try {
// 解析JSON响应体
const data = JSON.parse(xhr.responseText);
if (data.code !== 0) {
reject(new Error(data.msg || '翻译失败'));
return;
}
resolve(data.data);
} catch (error) {
reject(new Error('响应数据解析失败:' + error.message));
}
} else {
// 非2xx状态码视为失败
reject(new Error(`请求失败,状态码:${xhr.status},信息:${xhr.statusText}`));
}
}
};
// 6. 监控超时事件
xhr.ontimeout = function () {
reject(new Error('请求超时,请稍后重试'));
};
// 7. 监控网络错误(如断网)
xhr.onerror = function () {
reject(new Error('网络异常,请检查网络连接'));
};
// 8. 监控上传进度(可选,适用于文件上传场景)
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
const progress = (e.loaded / e.total) * 100;
console.log(`上传进度:${progress.toFixed(2)}%`);
}
};
// 9. 发送请求(JSON格式需手动序列化)
const requestData = JSON.stringify({ query, from, to });
xhr.send(requestData);
});
}
// 业务调用
async function useXHRTranslate() {
try {
const result = await baiduTranslateByXHR('你好世界', 'auto', 'en');
console.log('XHR翻译结果:', result.text);
} catch (error) {
console.error('XHR翻译失败:', error.message);
window.$message?.error(error.message);
}
}
优缺点
- 优点:兼容性极强(支持老旧浏览器)、可精细控制请求流程(进度监控、超时控制);
- 缺点:API繁琐、需手动处理JSON序列化/解析、不支持Promise链式调用(需手动封装Promise)。
2. fetch(现代原生API,替代XHR)
ES6+引入的现代原生请求API,基于Promise设计,语法更简洁,无需手动封装Promise,是原生请求的首选。
适用场景
- 现代浏览器/前端项目(不兼容IE);
- 无需复杂请求配置,追求轻量无依赖。
详细示例(含超时、取消请求)
javascript
/**
* fetch访问服务(含超时、取消请求)
* @param {string} query 待翻译文本
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<Object>} 翻译结果
*/
export async function baiduTranslateByFetch(query, from = 'auto', to = 'en') {
if (!query?.trim()) {
throw new Error('请传入有效的待翻译文本');
}
// 1. 创建AbortController(用于取消请求/设置超时)
const controller = new AbortController();
const signal = controller.signal;
// 2. 设置超时取消请求
const timeoutId = setTimeout(() => {
controller.abort(); // 超时后取消请求
throw new Error('请求超时,请稍后重试');
}, 8000);
try {
const response = await fetch('http://localhost:3000/api/translate/baidu', {
method: 'POST', // 请求方法
headers: {
'Content-Type': 'application/json', // JSON请求头
},
body: JSON.stringify({ query, from, to }), // 请求体序列化
signal: signal, // 关联取消信号
credentials: 'include' // 携带Cookie(跨域时需后端配合)
});
// 清除超时定时器
clearTimeout(timeoutId);
// 3. 判断响应是否成功(fetch仅在网络错误时抛出异常,非2xx状态码需手动判断)
if (!response.ok) {
throw new Error(`请求失败,状态码:${response.status},信息:${response.statusText}`);
}
// 4. 解析响应体(根据响应格式选择对应方法)
const data = await response.json(); // JSON格式
// const data = await response.text(); // 纯文本格式
// const data = await response.blob(); // 二进制文件格式
// 5. 处理业务错误
if (data.code !== 0) {
throw new Error(data.msg || '翻译失败');
}
return data.data;
} catch (error) {
// 捕获取消请求异常
if (error.name === 'AbortError') {
throw new Error('请求已被取消(超时/手动取消)');
}
throw new Error('fetch请求失败:' + error.message);
}
}
// 业务调用
async function useFetchTranslate() {
try {
const result = await baiduTranslateByFetch('测试文本', 'auto', 'en');
console.log('fetch翻译结果:', result.text);
} catch (error) {
console.error('fetch翻译失败:', error.message);
window.$message?.error(error.message);
}
}
优缺点
- 优点:语法简洁、基于Promise、无需第三方依赖、支持流式响应;
- 缺点:不兼容IE、非2xx状态码不自动抛出异常、超时/取消请求需手动通过AbortController实现、默认不携带Cookie。
3. SSE(Server-Sent Events,服务器单向推送)
基于HTTP协议的单向实时通信方式,由服务器主动向客户端推送数据(如消息通知、实时日志),前端无需轮询。
适用场景
- 服务器单向推送数据(如实时公告、数据监控、日志推送);
- 无需客户端向服务器发送实时数据的场景。
完整代码示例
javascript
/**
* 前端通过SSE接收服务器实时推送
* @param {string} url 服务器SSE接口地址
* @returns {EventSource} SSE实例
*/
export function createSSEConnection(url) {
// 1. 创建EventSource实例(自动保持长连接)
const eventSource = new EventSource(url, {
withCredentials: true // 携带Cookie(跨域时需后端配合)
});
// 2. 监听普通消息(服务器默认发送的message事件)
eventSource.onmessage = function (e) {
try {
const data = JSON.parse(e.data);
console.log('SSE接收普通消息:', data);
// 业务处理(如显示实时通知)
window.$message?.info(`实时通知:${data.content}`);
} catch (error) {
console.error('SSE消息解析失败:', error.message);
}
};
// 3. 监听自定义事件(服务器指定的事件类型)
eventSource.addEventListener('translateProgress', function (e) {
const progressData = JSON.parse(e.data);
console.log('翻译进度更新:', progressData.progress + '%');
});
// 4. 监听连接成功事件
eventSource.onopen = function () {
console.log('SSE连接成功,已建立长连接');
};
// 5. 监听错误事件
eventSource.onerror = function (e) {
if (eventSource.readyState === EventSource.CLOSED) {
console.error('SSE连接已关闭');
} else if (eventSource.readyState === EventSource.CONNECTING) {
console.warn('SSE连接断开,正在重连...');
} else {
console.error('SSE连接异常:', e);
}
};
// 6. 暴露关闭连接的方法
eventSource.closeConnection = function () {
eventSource.close();
console.log('SSE连接已手动关闭');
};
return eventSource;
}
// 业务调用
const sseInstance = createSSEConnection('http://localhost:3000/api/sse/translate');
// 手动关闭连接(如组件销毁时)
// sseInstance.closeConnection();
优缺点
- 优点:基于HTTP、无需额外协议、自动重连、轻量高效、支持自定义事件;
- 缺点:单向通信(客户端无法向服务器实时推送)、不支持二进制数据、部分浏览器兼容性有限。
4. WebSocket(双向实时通信)
基于TCP协议的全双工通信方式,客户端和服务器可双向实时传递数据,适用于实时交互场景。
适用场景
- 双向实时通信(如聊天系统、实时协作编辑、游戏互动);
- 高频数据交互(无需多次建立HTTP连接)。
完整代码示例
javascript
/**
* 前端通过WebSocket建立双向连接
* @param {string} url WebSocket服务器地址(ws://或wss://)
* @returns {WebSocket} WebSocket实例
*/
export function createWebSocketConnection(url) {
// 1. 创建WebSocket实例(ws://明文,wss://加密,对应HTTP/HTTPS)
const ws = new WebSocket(url);
// 2. 监听连接成功事件
ws.onopen = function () {
console.log('WebSocket连接成功');
// 连接成功后发送初始化消息
ws.send(JSON.stringify({
type: 'init',
data: '前端已连接'
}));
};
// 3. 监听服务器推送的消息
ws.onmessage = function (e) {
try {
const data = JSON.parse(e.data);
console.log('WebSocket接收消息:', data);
// 区分消息类型处理
switch (data.type) {
case 'translateResult':
console.log('实时翻译结果:', data.content);
window.$message?.success('翻译完成:' + data.content);
break;
case 'error':
console.error('WebSocket错误消息:', data.msg);
window.$message?.error(data.msg);
break;
default:
console.log('未知消息类型:', data);
}
} catch (error) {
console.error('WebSocket消息解析失败:', error.message);
}
};
// 4. 监听连接关闭事件
ws.onclose = function (e) {
console.log(`WebSocket连接关闭,代码:${e.code},原因:${e.reason}`);
// 可选:自动重连
if (e.code !== 1000) { // 1000表示正常关闭
setTimeout(() => {
console.log('WebSocket正在重连...');
createWebSocketConnection(url);
}, 3000);
}
};
// 5. 监听错误事件
ws.onerror = function (e) {
console.error('WebSocket连接异常:', e);
};
// 6. 暴露发送消息的方法(封装JSON序列化)
ws.sendMsg = function (type, data) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type, data }));
} else {
console.error('WebSocket未连接,无法发送消息');
}
};
return ws;
}
// 业务调用
const wsInstance = createWebSocketConnection('ws://localhost:3000/ws/translate');
// 发送翻译请求
wsInstance.sendMsg('translate', { query: '你好世界', from: 'auto', to: 'en' });
// 手动关闭连接
// wsInstance.close(1000, '客户端主动关闭');
优缺点
- 优点:全双工通信、实时性高、无HTTP请求头开销、支持二进制数据;
- 缺点:协议复杂(非HTTP)、需服务器支持WebSocket、重连逻辑需手动实现、跨域配置复杂。
5. JSONP(跨域兼容方案,现已基本淘汰)
基于<script>标签跨域特性实现的请求方式,仅支持GET请求,是老旧浏览器跨域的解决方案,现已被CORS替代。
适用场景
- 兼容不支持CORS的老旧浏览器(如IE8/9);
- 简单GET请求的跨域场景(现已极少使用)。
完整代码示例
javascript
/**
* JSONP请求(仅支持GET)
* @param {string} url 请求地址
* @param {Object} params 请求参数
* @param {string} callbackName 回调函数名
* @returns {Promise<Object>} 请求结果
*/
export function jsonpRequest(url, params, callbackName = 'jsonpCallback') {
return new Promise((resolve, reject) => {
// 1. 生成唯一回调函数名(避免冲突)
const uniqueCallbackName = `${callbackName}_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
// 2. 拼接请求参数(含回调函数名)
const paramStr = Object.keys(params).map(key => {
return `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`;
}).join('&') + `&callback=${uniqueCallbackName}`;
// 3. 创建script标签
const script = document.createElement('script');
script.src = `${url}?${paramStr}`;
script.type = 'text/javascript';
script.async = true;
// 4. 定义全局回调函数
window[uniqueCallbackName] = function (data) {
try {
resolve(data);
} finally {
// 清理全局函数和script标签
delete window[uniqueCallbackName];
document.body.removeChild(script);
}
};
// 5. 监听script加载错误
script.onerror = function () {
reject(new Error('JSONP请求失败'));
// 清理资源
delete window[uniqueCallbackName];
document.body.removeChild(script);
};
// 6. 插入script标签发起请求
document.body.appendChild(script);
});
}
// 业务调用
async function useJSONP() {
try {
const result = await jsonpRequest('https://xxx.com/api/public/translate', {
q: '你好世界',
from: 'auto',
to: 'en'
});
console.log('JSONP请求结果:', result);
} catch (error) {
console.error('JSONP请求失败:', error.message);
}
}
优缺点
- 优点:兼容老旧浏览器、无需后端配置CORS、实现简单;
- 缺点:仅支持GET请求、存在安全风险(易受XSS攻击)、无法监控请求进度/超时、现已基本被CORS替代。
二、第二类:第三方库请求方式(主流常用)
这类方式基于原生API封装,提供更简洁的语法、更强大的功能(如拦截器、取消请求、自动序列化),是现代前端开发的首选。
1. axios(最主流,功能完善)
基于Promise的HTTP请求库,支持浏览器和Node.js环境,封装了拦截器、超时控制、自动JSON解析等功能,生态完善。
适用场景
- 绝大多数前端项目(Vue/React/Angular等);
- 需复杂请求配置(拦截器、取消请求、批量请求)的场景。
详细示例(含拦截器、取消请求、批量请求)
javascript
import axios from 'axios';
// 1. 创建axios实例(统一配置基础参数)
const request = axios.create({
baseURL: 'http://localhost:3000/api', // 基础请求地址
timeout: 8000, // 全局超时时间
headers: {
'Content-Type': 'application/json' // 全局请求头
},
withCredentials: true // 全局携带Cookie
});
// 2. 请求拦截器(发送请求前处理,如添加token)
request.interceptors.request.use(
(config) => {
// 给所有请求添加token(登录后存储在localStorage)
const token = localStorage.getItem('token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
console.log('请求配置:', config);
return config;
},
(error) => {
// 请求错误预处理
console.error('请求拦截器错误:', error);
return Promise.reject(error);
}
);
// 3. 响应拦截器(接收响应后处理,如统一错误处理)
request.interceptors.response.use(
(response) => {
// 统一处理响应数据,只返回业务数据
return response.data;
},
(error) => {
// 统一处理响应错误
let errorMsg = '请求失败';
if (axios.isAxiosError(error)) {
if (error.response) {
// 有响应状态码的错误
const status = error.response.status;
const data = error.response.data;
switch (status) {
case 401:
errorMsg = '未登录或登录过期,请重新登录';
localStorage.removeItem('token');
// 跳转到登录页
window.location.href = '/login';
break;
case 403:
errorMsg = '无权限访问该资源';
break;
case 404:
errorMsg = '请求地址不存在';
break;
case 500:
errorMsg = '服务器内部错误,请稍后重试';
break;
default:
errorMsg = data.msg || `请求失败,状态码:${status}`;
}
} else if (error.request) {
// 无响应的错误(网络错误、超时)
errorMsg = '网络异常或请求超时,请检查网络连接';
}
}
console.error('响应拦截器错误:', errorMsg);
window.$message?.error(errorMsg);
return Promise.reject(new Error(errorMsg));
}
);
// 4. 翻译请求(基于封装的axios实例)
export async function baiduTranslateByAxios(query, from = 'auto', to = 'en') {
if (!query?.trim()) {
throw new Error('请传入有效的待翻译文本');
}
// 取消请求示例(创建取消令牌)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// 可选:手动取消请求(如组件销毁时)
// source.cancel('请求已被手动取消');
try {
const data = await request.post('/translate/baidu', {
query,
from,
to
}, {
cancelToken: source.token // 关联取消令牌
});
// 处理业务错误
if (data.code !== 0) {
throw new Error(data.msg || '翻译失败');
}
return data.data;
} catch (error) {
// 捕获取消请求异常
if (axios.isCancel(error)) {
console.log('请求已取消:', error.message);
} else {
throw error;
}
}
}
// 5. 批量请求示例(同时发起多个请求)
export async function batchTranslate(requestList) {
try {
// 同时发起多个翻译请求,等待所有请求完成
const results = await Promise.all(
requestList.map(item =>
request.post('/translate/baidu', {
query: item.query,
from: item.from || 'auto',
to: item.to || 'en'
})
)
);
return results.map(res => res.data);
} catch (error) {
console.error('批量翻译失败:', error.message);
throw error;
}
}
// 业务调用
async function useAxiosTranslate() {
try {
const result = await baiduTranslateByAxios('测试文本', 'auto', 'en');
console.log('axios翻译结果:', result.text);
// 批量翻译
const batchResult = await batchTranslate([
{ query: '你好' },
{ query: '世界', to: 'ja' }
]);
console.log('批量翻译结果:', batchResult);
} catch (error) {
console.error('axios翻译失败:', error.message);
}
}
优缺点
- 优点:语法简洁、支持拦截器、自动JSON解析、超时控制、取消请求、批量请求、兼容浏览器/Node.js;
- 缺点:需额外安装依赖(体积较小,影响可忽略)。
2. superagent(轻量灵活的请求库)
轻量的HTTP请求库,语法简洁,支持链式调用,功能丰富,适用于中小型项目。
适用场景
- 中小型前端项目;
- 追求轻量、灵活配置的场景。
完整代码示例
javascript
import superagent from 'superagent';
/**
* superagent请求翻译接口
* @param {string} query 待翻译文本
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<Object>} 翻译结果
*/
export async function baiduTranslateBySuperagent(query, from = 'auto', to = 'en') {
if (!query?.trim()) {
throw new Error('请传入有效的待翻译文本');
}
try {
const response = await superagent
.post('http://localhost:3000/api/translate/baidu') // 请求方法+地址
.set('Content-Type', 'application/json') // 设置请求头
.send({ query, from, to }) // 发送请求体
.timeout(8000) // 超时设置
.withCredentials(); // 携带Cookie
const data = response.body;
if (data.code !== 0) {
throw new Error(data.msg || '翻译失败');
}
return data.data;
} catch (error) {
let errorMsg = 'superagent请求失败';
if (error.timeout) {
errorMsg = '请求超时';
} else if (error.response) {
errorMsg = `请求失败,状态码:${error.response.status},信息:${error.response.text}`;
} else {
errorMsg = error.message;
}
console.error(errorMsg);
window.$message?.error(errorMsg);
throw new Error(errorMsg);
}
}
// 业务调用
async function useSuperagentTranslate() {
try {
const result = await baiduTranslateBySuperagent('你好世界', 'auto', 'en');
console.log('superagent翻译结果:', result.text);
} catch (error) {
console.error('superagent翻译失败:', error.message);
}
}
优缺点
- 优点:轻量小巧、语法简洁(链式调用)、支持流式响应、配置灵活;
- 缺点:生态不如axios完善、拦截器功能需手动封装。
3. Apollo Client(GraphQL专用请求库)
针对GraphQL接口的专用请求库,提供数据缓存、查询优化、状态管理等功能,适用于GraphQL项目。
适用场景
- 采用GraphQL接口的前端项目;
- 需数据缓存、批量查询优化的场景。
核心示例(基础查询)
javascript
import { ApolloClient, InMemoryCache, gql, useQuery } from '@apollo/client';
// 1. 创建Apollo Client实例
const client = new ApolloClient({
uri: 'http://localhost:3000/graphql', // GraphQL接口地址
cache: new InMemoryCache() // 内存缓存
});
// 2. 定义翻译查询
const TRANSLATE_QUERY = gql`
query Translate($query: String!, $from: String, $to: String) {
translate(query: $query, from: $from, to: $to) {
text
sourceText
from
to
provider
}
}
`;
// 3. 组件中使用查询(React示例)
export function TranslateComponent({ query, from, to }) {
const { loading, error, data } = useQuery(TRANSLATE_QUERY, {
variables: { query, from, to }, // 查询变量
fetchPolicy: 'cache-and-network' // 缓存策略
});
if (loading) return <div>翻译中...</div>;
if (error) return <div>翻译失败:{error.message}</div>;
return (
<div>
<p>原文:{data.translate.sourceText}</p>
<p>译文:{data.translate.text}</p>
<p>提供商:{data.translate.provider}</p>
</div>
);
}
// 4. 手动发起查询(非组件环境)
async function manualTranslate() {
try {
const result = await client.query({
query: TRANSLATE_QUERY,
variables: { query: '你好世界', from: 'auto', to: 'en' }
});
console.log('GraphQL翻译结果:', result.data.translate);
} catch (error) {
console.error('GraphQL查询失败:', error.message);
}
}
优缺点
- 优点:专为GraphQL设计、内置数据缓存、查询优化、支持订阅(实时数据);
- 缺点:仅适用于GraphQL接口、学习成本较高、体积较大。
三、第三类:跨端/框架内置请求方式
这类方式适用于跨端框架(如uni-app、小程序),由框架内置提供,兼容多端运行环境。
1. uni.request(uni-app/小程序跨端请求)
uni-app框架内置的跨端请求API,兼容微信小程序、支付宝小程序、H5、App等多个平台。
适用场景
- uni-app/微信小程序/支付宝小程序等跨端项目;
- 需一次编写、多端运行的场景。
完整代码示例
javascript
/**
* uni-app跨端翻译请求
* @param {string} query 待翻译文本
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<Object>} 翻译结果
*/
export function baiduTranslateByUniRequest(query, from = 'auto', to = 'en') {
return new Promise((resolve, reject) => {
if (!query?.trim()) {
reject(new Error('请传入有效的待翻译文本'));
return;
}
uni.request({
url: 'http://localhost:3000/api/translate/baidu', // 请求地址
method: 'POST', // 请求方法
header: {
'Content-Type': 'application/json' // 请求头
},
data: { query, from, to }, // 请求体
timeout: 8000, // 超时时间
success: (res) => {
const data = res.data;
if (data.code !== 0) {
reject(new Error(data.msg || '翻译失败'));
return;
}
resolve(data.data);
},
fail: (err) => {
const errorMsg = err.errMsg || 'uni.request请求失败';
console.error(errorMsg);
uni.showToast({
title: errorMsg,
icon: 'none'
});
reject(new Error(errorMsg));
}
});
});
}
// 业务调用(uni-app组件中)
async function useUniRequestTranslate() {
try {
const result = await baiduTranslateByUniRequest('你好世界', 'auto', 'en');
console.log('uni.request翻译结果:', result.text);
uni.showToast({
title: '翻译成功',
icon: 'success'
});
} catch (error) {
console.error('uni.request翻译失败:', error.message);
}
}
2. wx.request(微信小程序专属请求)
微信小程序框架内置的请求API,仅适用于微信小程序环境。
适用场景
- 纯微信小程序项目(非跨端);
- 需调用微信小程序特有接口的场景。
核心示例
javascript
/**
* 微信小程序翻译请求
* @param {string} query 待翻译文本
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<Object>} 翻译结果
*/
export function baiduTranslateByWxRequest(query, from = 'auto', to = 'en') {
return new Promise((resolve, reject) => {
if (!query?.trim()) {
reject(new Error('请传入有效的待翻译文本'));
return;
}
wx.request({
url: 'http://localhost:3000/api/translate/baidu',
method: 'POST',
header: {
'Content-Type': 'application/json'
},
data: { query, from, to },
timeout: 8000,
success: (res) => {
const data = res.data;
if (data.code !== 0) {
reject(new Error(data.msg || '翻译失败'));
return;
}
resolve(data.data);
},
fail: (err) => {
const errorMsg = err.errMsg || 'wx.request请求失败';
console.error(errorMsg);
wx.showToast({
title: errorMsg,
icon: 'none'
});
reject(new Error(errorMsg));
}
});
});
}
四、第四类:特殊场景:代理转发(本地/生产环境)
这不是直接的请求方式,而是解决跨域和敏感信息保护的辅助方案,分为本地开发代理和生产环境代理。
1. Vite/Webpack本地代理
本地开发时,通过Vite/Webpack配置代理,将前端请求转发到后端,规避浏览器跨域限制。
Vite代理配置示例(vite.config.js)
javascript
import { defineConfig } from 'vite';
export default defineConfig({
server: {
proxy: {
// 匹配/api开头的请求,转发到后端
'/api': {
target: 'http://localhost:3000', // 后端服务地址
changeOrigin: true, // 开启跨域模拟(修改请求头中的Host)
rewrite: (path) => path, // 路径重写(无需修改路径可省略,如需去掉/api则写 path.replace(/^\/api/, ''))
timeout: 10000 // 代理超时时间
},
// 单独配置WebSocket代理
'/ws': {
target: 'ws://localhost:3000',
ws: true, // 开启WebSocket代理
changeOrigin: true
},
// 配置SSE代理
'/sse': {
target: 'http://localhost:3000',
changeOrigin: true,
headers: {
'Accept': 'text/event-stream' // SSE响应头
}
}
}
}
});
配置后前端请求示例
javascript
// 无需写完整后端地址,直接写/api开头
const result = await axios.post('/api/translate/baidu', { query, from, to });
2. 生产环境Nginx代理
生产环境中,通过Nginx反向代理,将前端请求转发到后端服务,解决跨域和域名暴露问题。
Nginx配置示例(nginx.conf)
nginx
server {
listen 80;
server_name your-domain.com; # 你的前端域名
# 前端静态资源目录
root /usr/share/nginx/html;
index index.html;
# 解决Vue/React路由刷新404问题
location / {
try_files $uri $uri/ /index.html;
}
# 代理/api请求到后端
location /api/ {
proxy_pass http://127.0.0.1:3000/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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_timeout 10s; # 代理超时时间
}
# 代理WebSocket请求
location /ws/ {
proxy_pass ws://127.0.0.1:3000/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
# 代理SSE请求
location /sse/ {
proxy_pass http://127.0.0.1:3000/sse/;
proxy_set_header Host $host;
proxy_buffering off; # 关闭缓冲区,实时推送数据
proxy_cache off;
proxy_set_header Connection '';
chunked_transfer_encoding on;
}
}
五、各请求方式选型总结
| 请求方式 | 适用场景 | 推荐指数 | 核心优势 |
|---|---|---|---|
| axios | 现代前端项目(Vue/React等)、复杂请求配置 | ★★★★★ | 功能完善、拦截器、自动解析、生态丰富 |
| fetch | 现代浏览器、轻量无依赖场景 | ★★★★☆ | 原生无依赖、Promise化、语法简洁 |
| XMLHttpRequest | 老旧浏览器、精细控制请求流程 | ★★★☆☆ | 兼容性极强、支持进度监控 |
| WebSocket | 双向实时通信(聊天、协作) | ★★★★☆ | 实时性高、全双工通信 |
| SSE | 服务器单向实时推送(通知、监控) | ★★★☆☆ | 轻量、自动重连、基于HTTP |
| uni.request | uni-app/小程序跨端项目 | ★★★★☆ | 跨端兼容、一次编写多端运行 |
| Apollo Client | GraphQL接口项目 | ★★★★☆ | 内置缓存、查询优化、支持订阅 |
| superagent | 中小型项目、追求轻量灵活 | ★★★☆☆ | 轻量小巧、链式调用 |
| JSONP | 老旧浏览器跨域(现已极少使用) | ★★☆☆☆ | 兼容老旧浏览器、无需后端CORS |
六、核心注意事项(通用避坑指南)
- 跨域问题:本地开发用Vite/Webpack代理,生产环境用Nginx代理/后端CORS配置;
- 敏感信息保护:涉及appid/secretKey/token的请求,必须通过后端中转,前端不存储敏感信息;
- 异常处理:所有请求必须用try/catch捕获异常,区分网络错误、业务错误、超时错误;
- 超时控制:所有请求都应设置超时时间,避免前端长时间等待;
- 数据序列化:JSON请求需确保请求体序列化,响应体正确解析;
- 取消请求:组件销毁/页面跳转时,取消未完成的请求,避免内存泄漏。
以上就是前端访问服务的详细方法和补充方案,覆盖了绝大多数开发场景,可根据项目类型和需求选择合适的方式。