7.1 wx.request 基础
wx.request 是小程序发起 HTTP 网络请求的基础 API,支持 GET/POST/PUT/DELETE 等方法。有几个重要限制需要了解:
域名白名单限制
小程序只能请求在微信公众平台后台配置了合法域名的服务器(开发模式下可临时关闭验证)。进入「开发管理 → 开发设置 → 服务器域名」,将你的 API 域名添加到 request 合法域名列表。域名必须是 HTTPS,不支持 HTTP(除 localhost 调试)。
封装 request 工具类
// utils/request.js — 生产可用的请求封装
const BASE_URL = 'https://api.example.com'
const TIMEOUT = 10000
// 将 wx.request 包装为 Promise
function request(options) {
return new Promise((resolve, reject) => {
const app = getApp()
const token = app.globalData.token
wx.request({
url: BASE_URL + options.url,
method: options.method || 'GET',
data: options.data,
timeout: TIMEOUT,
header: {
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token}` : '',
...options.header
},
success(res) {
if (res.statusCode === 200) {
const data = res.data
if (data.code === 0) {
resolve(data.data)
} else if (data.code === 401) {
// Token 过期,跳转登录
wx.redirectTo({ url: '/pages/login/login' })
reject(new Error('未登录'))
} else {
reject(new Error(data.message || '请求失败'))
}
} else {
reject(new Error(`HTTP ${res.statusCode}`))
}
},
fail(err) {
if (err.errMsg.includes('timeout')) {
reject(new Error('网络超时,请重试'))
} else {
reject(new Error('网络异常,请检查连接'))
}
}
})
})
}
// 便捷方法
const http = {
get: (url, data, header) => request({ url, data, header, method: 'GET' }),
post: (url, data, header) => request({ url, data, header, method: 'POST' }),
put: (url, data, header) => request({ url, data, header, method: 'PUT' }),
delete: (url, data, header) => request({ url, data, header, method: 'DELETE' })
}
module.exports = http
// 使用示例
const http = require('../../utils/request')
async fetchProducts() {
try {
const data = await http.get('/products', { page: 1, size: 20 })
this.setData({ products: data.items })
} catch (e) {
wx.showToast({ title: e.message, icon: 'error' })
}
}
7.2 云开发 CloudBase
云开发(CloudBase)是腾讯为小程序提供的 Serverless 后端服务,开发者无需购买服务器,直接在前端调用云数据库、云存储和云函数。
初始化云开发
// app.js
App({
onLaunch() {
wx.cloud.init({
env: 'your-env-id', // 云开发环境 ID(在云开发控制台查看)
traceUser: true // 是否将用户访问记录到用户管理
})
}
})
云数据库操作
// 获取数据库引用
const db = wx.cloud.database()
const _ = db.command // 查询/更新操作符
// ─── 查询 ───
// 查询单条
const product = await db.collection('products')
.doc('product-id-123')
.get()
console.log(product.data)
// 条件查询(带过滤、排序、分页)
const result = await db.collection('products')
.where({
category: 'electronics',
price: _.lt(1000), // price < 1000
stock: _.gt(0) // stock > 0
})
.orderBy('createdAt', 'desc')
.skip((page - 1) * pageSize)
.limit(pageSize)
.get()
// 聚合查询
const stats = await db.collection('orders')
.aggregate()
.match({ userId: 'current-user-id' })
.group({
_id: '$status',
count: $.sum(1),
total: $.sum('$amount')
})
.end()
// ─── 新增 ───
const addRes = await db.collection('comments').add({
data: {
content: '很好的商品!',
productId: 'product-id-123',
createdAt: db.serverDate() // 使用服务器时间
}
})
// ─── 更新 ───
await db.collection('products').doc('product-id-123').update({
data: {
stock: _.inc(-1), // 原子减 1(防并发)
viewCount: _.inc(1),
tags: _.push(['hot']) // 向数组追加元素
}
})
// ─── 删除 ───
await db.collection('comments').doc('comment-id').remove()
云存储
// 上传文件
const uploadImage = async () => {
// 1. 选择图片
const chooseRes = await wx.chooseMedia({
count: 1,
mediaType: ['image'],
sizeType: ['compressed']
})
const tempFilePath = chooseRes.tempFiles[0].tempFilePath
// 2. 上传到云存储
const cloudPath = `avatars/${Date.now()}.jpg`
const uploadRes = await wx.cloud.uploadFile({
cloudPath,
filePath: tempFilePath
})
// 3. 获取访问 URL
const { fileList } = await wx.cloud.getTempFileURL({
fileList: [uploadRes.fileID]
})
return fileList[0].tempFileURL
}
云函数
// cloudfunctions/getOpenId/index.js(服务端代码)
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
exports.main = async (event, context) => {
const { OPENID, UNIONID } = cloud.getWXContext()
return { openId: OPENID, unionId: UNIONID }
}
// 小程序端调用云函数
const res = await wx.cloud.callFunction({
name: 'getOpenId',
data: { /* 传给云函数的参数 */ }
})
console.log('openId:', res.result.openId)
7.3 本地缓存策略
// 同步存储(少量数据,会阻塞)
wx.setStorageSync('userInfo', userInfo)
const cached = wx.getStorageSync('userInfo')
// 异步存储(推荐,不阻塞逻辑层)
await wx.setStorage({ key: 'token', data: 'jwt...' })
const { data: token } = await wx.getStorage({ key: 'token' })
// 带过期时间的缓存封装
const cache = {
set(key, data, ttlSeconds = 3600) {
wx.setStorageSync(key, {
data,
expireAt: Date.now() + ttlSeconds * 1000
})
},
get(key) {
try {
const item = wx.getStorageSync(key)
if (!item) return null
if (item.expireAt < Date.now()) {
wx.removeStorageSync(key)
return null
}
return item.data
} catch {
return null
}
}
}
// 使用:先读缓存,缓存失效再请求
async getCategories() {
const cached = cache.get('categories')
if (cached) return cached
const data = await http.get('/categories')
cache.set('categories', data, 60 * 60) // 缓存 1 小时
return data
}
缓存容量限制
单个 key 存储上限为 1 MB,单个小程序总存储上限为 10 MB。存储大量数据(如图片列表)时要注意控制大小,定期清理过期缓存。可用 wx.getStorageInfoSync() 查看当前已用空间。