小程序 wx.request 如何封装?网络请求有哪些限制和注意点?
简化版
wx.request 是小程序发起 HTTPS 请求的主要 API,工程里通常会封装 baseURL、header、token、错误处理、loading、超时、重试和登录失效逻辑。注意小程序请求受合法域名、HTTPS、并发数、超时和客户端环境限制,安全校验必须放服务端。
详细版
常见封装点:
- 统一
baseURL和路径拼接。 - 自动携带登录态 token。
- 统一处理 HTTP 状态码和业务 code。
- 处理 loading、toast、错误日志。
- 支持超时、取消、重试和防重复提交。
示例:
function request({ url, method = 'GET', data }) {
return new Promise((resolve, reject) => {
wx.request({
url: BASE_URL + url,
method,
data,
header: { Authorization: `Bearer ${getToken()}` },
success(res) {
res.statusCode === 200 ? resolve(res.data) : reject(res)
},
fail: reject
})
})
}
面试回答要强调:前端封装提升体验和一致性,但鉴权、权限、金额、幂等、风控都必须由服务端保证。
完整版教学
一、wx.request 是小程序网络层入口
小程序运行在微信客户端容器中,不能直接使用浏览器的 fetch 或 XMLHttpRequest。常见网络请求通过 wx.request 发出。
wx.request({
url: 'https://api.example.com/goods',
method: 'GET',
success(res) {
console.log(res.data)
},
fail(err) {
console.error(err)
}
})
它的模型和 Web 前端请求相似,但受小程序平台规则约束,例如合法域名配置、HTTPS 要求、请求并发和基础库能力。面试时不能只按浏览器 Ajax 来答。
如果一个项目有 50 个接口,所有页面都手写 wx.request,很快会出现 token 处理不一致、错误提示不统一、登录失效逻辑重复等问题,所以工程里通常会封装请求层。
二、封装请求层要统一协议
请求封装的第一目标是统一接口协议:baseURL、header、token、状态码、业务 code、错误提示和日志。这样页面只关心业务数据,不关心每次请求怎么拼。
const BASE_URL = 'https://api.example.com'
export function request(options) {
return new Promise((resolve, reject) => {
wx.request({
url: BASE_URL + options.url,
method: options.method || 'GET',
data: options.data,
timeout: options.timeout || 10000,
header: {
'content-type': 'application/json',
Authorization: getToken() ? `Bearer ${getToken()}` : ''
},
success(res) {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data)
} else {
reject(res)
}
},
fail: reject
})
})
}
假设 20 个页面都要处理 401 登录失效,如果不封装,就要复制 20 份跳登录逻辑;封装后只要在一处处理,体验和维护成本都会更稳定。
三、HTTP 状态码和业务 code 要分层处理
HTTP 状态码表示协议层结果,业务 code 表示业务层结果。二者不能混为一谈。statusCode=200 只说明请求成功到达并收到响应,不代表业务一定成功。
{
"code": 10001,
"message": "登录已过期",
"data": null
}
常见处理流程:
wx.request 成功回调
-> 先看 HTTP statusCode
-> 再看业务 code
-> 成功返回 data
-> 登录失效跳登录
-> 业务错误提示 message
| 层级 | 示例 | 处理方式 |
|---|---|---|
| 网络失败 | 断网、DNS、超时 | fail、重试或提示 |
| HTTP 失败 | 500、404、403 | 错误页、告警、权限提示 |
| 业务失败 | 库存不足、登录过期 | toast、跳登录、刷新状态 |
| 成功 | 200 + code 0 | 返回业务 data |
这样分层后,页面不会把服务器 500 当成“库存不足”,也不会把业务错误误认为网络断开。
四、合法域名和 HTTPS 是小程序特有边界
小程序不能随便请求任意域名,生产环境通常要求在后台配置 request 合法域名,并使用 HTTPS。这是平台安全和治理要求。
小程序代码
-> wx.request
-> 微信客户端校验域名
-> 通过后请求业务服务
开发者工具里可能有“不校验合法域名”的调试选项,但线上不能依赖它。很多上线事故就是本地能请求,真机或线上因为域名未配置、证书错误、协议不对而失败。
如果有多个环境,例如 dev、test、prod,不能让用户包动态请求未配置域名。工程上要明确环境构建方式和域名白名单。
易错点:小程序请求失败不一定是代码错,也可能是平台域名、证书、网络环境或基础库限制导致。
五、登录态、刷新 token 和并发请求
接口封装常见难点是登录态过期。多个请求同时返回 401 时,如果每个请求都跳登录或刷新 token,会造成重复弹窗、重复刷新和状态混乱。
请求 A -> 401
请求 B -> 401
请求 C -> 401
-> 只触发一次刷新 token
-> 其他请求等待刷新结果
-> 刷新成功后重放或失败后跳登录
可以用一个全局 refreshing 状态和等待队列控制。数字例子:首页同时发 8 个接口,token 过期时只应该发 1 次刷新请求,而不是 8 次。
此外,写操作还要考虑防重复提交。按钮禁用只能改善体验,真正幂等要靠服务端幂等 key、订单状态机或唯一约束。
六、请求体验和可观测性也要封装
成熟请求层不只是“Promise 化”。还要处理 loading、空状态、错误提示、上报日志、trace id、超时和重试策略。
发起请求
-> 生成 requestId
-> 展示局部 loading
-> 超时或失败分类
-> 上报接口耗时和错误
-> 收尾隐藏 loading
重试要谨慎。GET 查询在弱网下可以有限重试,比如最多 2 次;创建订单、支付、提交表单这类写操作不能无脑重试,必须结合幂等设计。
如果接口 P95 耗时从 300ms 变成 1800ms,前端封装层记录耗时和 requestId,就能帮助后端排查。没有统一日志,用户只会看到“加载失败”,定位会很痛苦。
七、常见误区与追问
- 误区:wx.request 和浏览器 fetch 完全一样。 小程序请求受微信客户端、合法域名、基础库和平台规则约束。
- 误区:HTTP 200 就代表业务成功。 还要看业务 code,登录过期、库存不足都可能在 200 响应里表达。
- 误区:前端封装 token 就完成安全。 token 校验、权限、金额、幂等都必须由服务端保证。
- 追问:多个请求同时 401 怎么处理? 用刷新锁和等待队列,只刷新一次 token,再决定重放或跳登录。
- 追问:哪些请求可以重试? 幂等的查询请求可以有限重试,写操作必须有服务端幂等保障。
- 追问:本地能请求线上失败常见原因? 合法域名未配置、HTTPS 证书问题、环境域名错误或真机网络差异。
八、加强记忆
小程序请求封装按“四层”记:平台层看域名和 HTTPS,协议层看 HTTP 状态码,业务层看 code,体验层管 loading、重试、日志和登录态。封装能让页面少写重复代码,但不能把安全边界搬到前端。