当前位置: 首页 > news >正文

《微信小程序》第三章:Request封装

系列文章

《微信小程序》https://blog.csdn.net/sen_shan/category_13069009.html

第二章:第一个程序https://blog.csdn.net/sen_shan/article/details/153685143?spm=1001.2014.3001.5501

文章目录

目录

系列文章

文章目录

前言

Toast封装

Request封装

 后续


前言

        本文介绍了微信小程序开发中的两个核心工具封装:Toast提示和Request请求。

        Toast封装通过统一配置解决了提示时长不一致、图标类型错误和错误提示样式问题;        

        Request封装则构建了一个类型安全的网络请求层,统一处理域名配置、超时设置、Header管理、Token携带、错误提示等功能,并内置了401登录失效自动处理机制。文章重点展示了如何通过TypeScript类型系统提升开发体验,使业务代码只需关注核心逻辑,同时保持对请求参数和返回数据的类型安全。这些封装旨在减少重复代码,提高开发效率和代码可维护性。

Toast封装

在 WechatMiniApp 项目下新建  src/utils/toast.ts 

type ToastIcon = 'success' | 'loading' | 'none' | undefinedconst DEFAULT_OPTS = {duration: 4000, // 统一 4 秒icon: 'success' as ToastIcon,
}export function toast(title: string, icon?: ToastIcon, duration = DEFAULT_OPTS.duration) {uni.showToast({ title, icon: icon ?? DEFAULT_OPTS.icon, duration })
}// 可选:错误专用(红色图标/更长)
export function toastError(title: string) {toast(title, 'none', 5000)
}

解决调用 uni.showToast 时出现的 3 类问题:
1. 提示时长不统一(2 s / 3 s / 5 s 随意写)。
2. 图标类型写错(success 拼成 succes、loading 写成 load)。
3. 错误提示样式与正常提示无区分,用户感知弱。

Request封装

在 WechatMiniApp 项目下新建  src/utils/reques.ts

// 顶部引入
import { toastError } from './toast'
/* 配置 ------------------------------------------------------------------ */
const BASE_URL = 'http://127.0.0.1:8080' // 替换你的后端域名
const TIMEOUT = 10_000 // ms/* 类型定义 --------------------------------------------------------------- */
export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE'export interface RequestOptions<T = any> {url: stringmethod?: Methoddata?: Theaders?: Record<string, string>noToken?: boolean // 跳过 tokennoBaseURL?: boolean // 跳过 baseURLtimeout?: number
}// 后端统一返回格式(按你的实际改)
export interface HttpResponse<T = any> {status_code: numbermessage: stringdata: T
}/* 核心请求 --------------------------------------------------------------- */
export function request<R = any, T = any>(options: RequestOptions<T>): Promise<R> {return new Promise((resolve, reject) => {const token = uni.getStorageSync('token')const header: AnyObject = {'Content-Type': 'application/json; charset=utf-8','x-api-key': 'ae139f8f6a8efc2a74a1e852c5cdaa43', // ← 新增这一行...options.headers,}if (!options.noToken && token) header.Authorization = `Bearer ${token}`uni.request({url: options.noBaseURL ? options.url : `${BASE_URL}${options.url}`,method: options.method || 'GET',data: options.data || {},header,timeout: options.timeout || TIMEOUT,success: (res) => handleSuccess<R>(res, resolve, reject),fail: (err) => handleFail(err, reject),})})
}/* 成功处理 --------------------------------------------------------------- */
function handleSuccess<R>(res: UniApp.RequestSuccessCallbackResult,resolve: (value: R) => void,reject: (reason?: any) => void,
) {const { statusCode, data } = res// 成功区间if (statusCode >= 200 && statusCode < 300) {const resp = data as HttpResponse<R>console.log(resp)// 后端业务码自定义,这里以 0 为成功if (resp.status_code === 200) resolve(resp.data)else {toastError( resp.message)reject(resp)}return}// 401 登录态失效// if (statusCode === 401) {//   uni.clearStorageSync()//   uni.reLaunch({ url: '/pages/login/index' })//   reject(new Error('登录已过期'))//   return// }if (statusCode === 401) {const detail = (data as any)?.detail || '登录已过期'// uni.showToast({ title: detail, // 	icon: 'none',// 	duration: 5000, // 5 秒// })   // 需要提示就留,不需要就删toastError( detail)   // 需要提示就留,不需要就删uni.clearStorageSync()uni.reLaunch({ url: '/pages/login/index' })reject(new Error(detail))return}if (statusCode !== 401 && statusCode >= 300 ) {const detail = (data as any)?.detail || '登录已过期'// uni.showToast({ title: detail, // 	icon: 'none',// 	duration: 5000, // 5 秒// })   // 需要提示就留,不需要就删toastError( detail)   // 需要提示就留,不需要就删uni.clearStorageSync()// uni.reLaunch({ url: '/pages/login/index' })reject(new Error(detail))return}// 其他 HTTP 错误//uni.showToast({ title: `请求失败(${statusCode})`, icon: 'none' })toastError( `请求失败(${statusCode})`)reject(new Error(JSON.stringify(data)))
}/* 失败处理 --------------------------------------------------------------- */
function handleFail(err: any, reject: (reason?: any) => void) {// uni.showToast({ title: '网络异常', icon: 'none' })toastError( `网络异常`)reject(err)
}/* 上传文件 --------------------------------------------------------------- */
export function upload<R = any>(url: string,filePath: string,formData?: Record<string, any>,timeout = 30_000,
): Promise<R> {const token = uni.getStorageSync('token')return new Promise((resolve, reject) => {uni.uploadFile({url: `${BASE_URL}${url}`,filePath,name: 'file',formData,header: { Authorization: `Bearer ${token}` },timeout,success: (res) => {// uploadFile 返回字符串,先 parseconst data: HttpResponse<R> = JSON.parse(res.data)if (data.status_code === 0) resolve(data.data)else {uni.showToast({ title: data.message || '上传失败', icon: 'none' })reject(data)}},fail: reject,})})
}/* 导出别名(可选)-------------------------------------------------------- */
export const http = { get: <R = any>(url: string, params?: any) => request<R>({ url, data: params }),post: <R = any>(url: string, data?: any) => request<R>({ url, method: 'POST', data }),put: <R = any>(url: string, data?: any) => request<R>({ url, method: 'PUT', data }),delete: <R = any>(url: string) => request<R>({ url, method: 'DELETE' }) }

目的
1. 在 uni-app 项目里提供“一处配置、处处可用”的网络请求层,统一接管:
        域名、超时、header、token、错误提示;
        业务状态码与 HTTP 状态码的双重校验;
        401 登录失效的自动清理与跳登录页;
        所有异常统一使用  toastError  弹出红色错误提示,避免每个接口重复写  uni.showToast 。
2. 通过 TypeScript 泛型与类型定义,让调用者在编译期即可获得:
        请求参数提示 ( RequestOptions<T> );
        返回数据结构提示 ( HttpResponse<R>  → 直接拿到  R )。
3. 额外内置文件上传常用  get/post/put/delete  别名,业务层基本不再需要自己拼  uni.request 。
核心功能
        自动携带  x-api-key  与  Authorization (Bearer token),其中x-api-key自定义字段,按需增加
        支持开关  noToken 、 noBaseURL ,方便调第三方开放接口。
        200–300 之间且业务码  status_code === 200  才走  resolve ,否则弹错并  reject 。
        401 场景:清缓存 → 跳登录页 → 返回  reject ,防止死循环。
        网络层或 HTTP 异常统一  toastError  提示,业务只需  .catch()  即可,无需再写提示逻辑。
把“发请求-拼头-验码-弹错-登出”全部收拢,业务代码只关心  url  和  data 。

 后续

        1.Request应用案例

        2.参数封装

http://www.dtcms.com/a/515164.html

相关文章:

  • 破空驭风,智领未来 --5KG物流配送无人机展示飞行!
  • 全面掌握 PostgreSQL 关系型数据库,PostgreSQL 和 MySQL 的区别,笔记03
  • 做RAG的开发者如何选择合适的开源项目
  • Spring Boot整合JWT实现跨站点统一登录
  • Spring Boot Docker镜像分层优化指南
  • Linux中页面写回初始化page_writeback_init函数实现
  • 神经网络中的随机高斯初始化技术
  • 怎样做网站分流赚钱东莞网站制作哪家公司好
  • HOOPS 3D可视化引擎:覆盖实时渲染与仿真分析的高性能解决方案!
  • 云原生架构下微服务接入 SkyWalking 最佳实践
  • 单片机中的机器周期、指令周期、总线周期的联系和区别
  • spring微服务宏观概念
  • 在阿里云通过docker部署srs流媒体服务器(支持webrtc、http-flv)
  • 【WAF】 Nginx如何集成安全检测服务
  • nginx安装和使用
  • 茂名市建设银行网站今天哈尔滨最新通告
  • 快飞建站月夜直播免费版
  • Windows 11 25H2 更新补丁导致鼠标键盘失灵,紧急更新补丁已推出
  • 移动端 (RN) - 键盘弹出, 不遮挡输入框 (和 底部按钮)的处理方案
  • 【C++闯关笔记】深究继承
  • Python爬虫抓取豆瓣TOP250数据
  • AWS Elemental MediaConvert:视频转码不再难
  • 华为OD最新机试真题-乘坐保密电梯-OD统一考试(C卷)
  • SpringBoot 如何实现零拷贝:深度解析零拷贝技术
  • 问卷调查网站怎么做做百度推广
  • Jenkins 持续集成与部署指南
  • 新书速览|DeepSeek高效数据分析:从数据清洗到行业案例
  • 搜索百科(5):Easysearch — 自主可控的国产分布式搜索引擎
  • 自己建商城型网站做设计的软件
  • # 模型量化(二):基于BERT的量化代码实战