uni-app 網絡之封裝實戰HTTP請求框架

前言

在uniapp開發中,網絡請求是每個應用都必不可少的功能模塊。一個優秀的網絡請求封裝不僅能提高開發效率,還能增強代碼的可維護性和可擴展性。本文將基于實際項目經驗,詳細介紹如何封裝一個高效、可維護的Uniapp網絡請求框架,并結合必應圖片API的調用示例,展示其完整使用流程。

一、網絡請求封裝的核心目標

  1. 統一管理:集中管理請求配置、攔截器等
  2. 復用性:減少重復代碼,提高開發效率
  3. 可擴展性:方便添加新功能如日志記錄、錯誤處理等
  4. 可維護性:清晰的代碼結構,便于團隊協作

二、封裝架構設計

1.項目結構規劃

項目根目錄下新建文件夾common,在其目錄下新建 api 文件夾以及 vmeitime-http 文件夾 ,如下

common/
├── api/? ? ? ? ? ? ? ?# API接口管理
│? ?└── index.js? ? ? ?# 接口統一出口
└── vmeitime-http/? ? ?# HTTP核心封裝├── http.js? ? ? ? # 請求核心實現└── interface.js? ?# 基礎請求方法

然后再項目根目錄下的main.js下引用

//api
import api from '@/common/api/index.js'
Vue.prototype.$api = api

2.核心組件解析

(1) 基礎請求層 (interface.js)

這是整個框架的基石,實現了:

  • 基礎請求方法(GET/POST/PUT/DELETE)
  • 請求超時處理
  • 請求ID生成(便于日志追蹤)
  • 基礎配置管理
/*** 通用uni-app網絡請求* 基于 Promise 對象實現更簡單的 request 使用方式,支持請求和響應攔截*/
export default {config: {baseUrl: "",header: {'Content-Type': 'application/x-www-form-urlencoded'},data: {},method: "POST",dataType: "json",/* 如設為json,會對返回的數據做一次 JSON.parse */responseType: "text",timeout: 15000, // 全局超時時間 15 秒fail() {},complete() {}},interceptor: {request: null,response: null},request(options) {if (!options) {options = {}}// 1. 生成唯一請求ID并掛載到optionsconst requestId = generateRequestId();options.requestId = requestId; // 給請求配置添加IDoptions.baseUrl = options.baseUrl || this.config.baseUrloptions.dataType = options.dataType || this.config.dataTypeoptions.url = options.baseUrl + options.urloptions.data = options.data || {}options.method = options.method || this.config.methodoptions.timeout = options.timeout || this.config.timeout; // 使用配置的超時時間return new Promise((resolve, reject) => {let _config = nulllet timeoutHandle = null;// 超時處理if (options.timeout) {timeoutHandle = setTimeout(() => {reject({errMsg: "request:fail timeout",timeout: true,requestId: requestId // 超時錯誤也攜帶ID,方便定位});}, options.timeout);}options.complete = (response) => {// 無論成功失敗,都清除超時計時器clearTimeout(timeoutHandle);_config = Object.assign({}, this.config, options);response.config = _config; // 給響應掛載配置,供攔截器使用// 執行響應攔截器if (this.interceptor.response) {const interceptedResponse = this.interceptor.response(response);if (interceptedResponse !== undefined) {response = interceptedResponse;}}// 統一的響應日志記錄_reslog(response)if (response.statusCode === 200) { //成功resolve(response);} else {reject(response)}}// 失敗回調(網絡錯誤等)options.fail = (error) => {clearTimeout(timeoutHandle);error.requestId = requestId; // 網絡錯誤攜帶IDconsole.error(`【網絡請求失敗】ID: ${requestId}`, error);uni.showToast({title: error.timeout ? "請求超時" : "網絡連接失敗,請檢查網絡",icon: "none"});reject(error);};// 執行請求攔截器_config = Object.assign({}, this.config, options);if (this.interceptor.request) {const interceptedConfig = this.interceptor.request(_config);if (interceptedConfig !== undefined) {_config = interceptedConfig;}}// 統一的請求日志記錄_reqlog(_config)uni.request(_config);});},get(url, data, options) {if (!options) {options = {}}options.url = urloptions.data = dataoptions.method = 'GET'return this.request(options)},post(url, data, options) {if (!options) {options = {}}options.url = urloptions.data = dataoptions.method = 'POST'return this.request(options)},put(url, data, options) {if (!options) {options = {}}options.url = urloptions.data = dataoptions.method = 'PUT'return this.request(options)},delete(url, data, options) {if (!options) {options = {}}options.url = urloptions.data = dataoptions.method = 'DELETE'return this.request(options)}
}/*** 請求接口日志記錄*/function _reqlog(req) {//開發環境日志打印if (process.env.NODE_ENV === 'development') {const reqId = req.requestId || '未知ID'; // 讀取請求IDconst reqUrl = req.url || '未知URL'; // 讀取完整URLconsole.log(`【${reqId}】 地址:${reqUrl}`);if (req.data) {console.log("【" + (req.requestId || '未知ID') + "】 請求參數:", req.data);}}
}/*** 響應接口日志記錄*/
function _reslog(res) {if (!res) {console.error("【日志錯誤】響應對象為空");return;}const requestId = res.config?.requestId || '未知請求ID';const url = res.config?.url || '未知URL';const statusCode = res.statusCode || '未知狀態碼';console.log(`【${requestId}】 接口: ${url} | 業務狀態碼: ${statusCode}`);// 打印響應數據if (res.data) {console.log(`【${requestId}】 響應數據:`, res.data);}// 錯誤處理邏輯switch (statusCode) {case "401":console.error(`【${requestId}】 未授權錯誤`);break;case "404":console.error(`【${requestId}】 接口不存在`);break;case "500":console.error(`【${requestId}】 服務器錯誤`);break;default:}
}
/*** 生成唯一請求ID(時間戳+隨機數,避免重復)*/
function generateRequestId() {const timestamp = Date.now().toString(36); // 時間戳轉36進制(縮短長度)const randomStr = Math.random().toString(36).slice(2, 8); // 6位隨機字符串return `${timestamp}-${randomStr}`; // 格式:時間戳-隨機串(如:1h8z2x-9k7a3b)
}

(2) 請求增強層 (http.js)

在基礎層之上添加:

  • 全局攔截器(請求/響應)
  • 公共參數處理
  • 錯誤統一處理
  • 默認配置初始化
import uniRequest from './interface'uniRequest.config.baseUrl = "https://cn.bing.com"
uniRequest.config.header = {'Content-Type': 'application/x-www-form-urlencoded'
}// 公共參數(所有請求都會攜帶)
const commonParams = {};//設置請求前攔截器
uniRequest.interceptor.request = (config) => {//添加通用參數let token = uni.getStorageSync('token');if (token) {config.header["X-Token"] = token;}// 合并公共參數和業務參數const mergedData = {...commonParams, // 公共參數...config.data // 業務參數(會覆蓋公共參數)};config.data = mergedData;return config;
}
//設置請求結束后攔截器
uniRequest.interceptor.response = (response) => {return response;
}export default uniRequest

(3) API接口層 (api/index.js)

import http from '@/common/vmeitime-http/http.js'const $api = {//查看必應圖片byImageList(data) {return http.request({url: '/HPImageArchive.aspx?format=js&idx=0&n=1',method: 'GET',data,})}
}
export default $api

三、使用示例:調用Bing圖片API

<template><view><!-- 顯示加載狀態 --><view v-if="loading" class="loading">{{ tooltips.loading }}</view><!-- 顯示Bing圖片 --><image v-else :src="fullImageUrl" mode="widthFix" class="bing-image"></image></view>
</template><script>export default {data() {return {loading: true, // 加載狀態fullImageUrl: "", // 拼接后的完整圖片URL};},onLoad() {uni.showLoading({title: '請稍后',mask: true // 防止用戶重復操作});this.fetchBingImage().finally(() => {this.loading = false; // 確保 loading 被關閉uni.hideLoading(); // 無論成功失敗都關閉加載框});},methods: {fetchBingImage() {return this.$api.byImageList().then(res => {console.log("請求成功:", res);console.log('images 數組:', res.data.images);// 2. 提取 images 數組的第一項const imageData = res.data.images[0];console.log('images圖片:', imageData.url);// 3. 拼接完整URL(http://cn.bing.com + url)this.fullImageUrl = `https://cn.bing.com${imageData.url}`;console.log('images圖片地址:', this.fullImageUrl);}).catch(err => {// 此時的err只可能是:HTTP錯誤、解析異常、業務失敗(result≠0000)console.error("請求失敗:", err);uni.showToast({title: err.error || err.timeout ? '請求超時' : '請求失敗',icon: 'none',duration: 2000});return Promise.reject(err); // 繼續拋出,供上層處理});},},};
</script><style>.loading {font-size: 16px;color: #999;text-align: center;margin-top: 50px;}.bing-image {width: 100%;height: auto;}
</style>

四、高級功能實現

1. 日志系統

// 請求日志
function _reqlog(req) {if (process.env.NODE_ENV === 'development') {console.log(`【${req.requestId}】 地址:${req.url}`);if (req.data) {console.log("請求參數:", req.data);}}
}// 響應日志
function _reslog(res) {const requestId = res.config?.requestId || '未知請求ID';console.log(`【${requestId}】 接口: ${res.config?.url} | 狀態碼: ${res.statusCode}`);// 錯誤狀態碼處理switch (res.statusCode) {case 401: console.error(`未授權錯誤`); break;case 404: console.error(`接口不存在`); break;case 500: console.error(`服務器錯誤`); break;}
}

2. 請求ID生成算法

function generateRequestId() {const timestamp = Date.now().toString(36); // 時間戳轉36進制const randomStr = Math.random().toString(36).slice(2, 8); // 6位隨機字符串return `${timestamp}-${randomStr}`; // 格式:時間戳-隨機串
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/922462.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/922462.shtml
英文地址,請注明出處:http://en.pswp.cn/news/922462.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

架構師成長之路-架構方法論

文章目錄前言一、先搞懂&#xff1a;架構師不僅僅是“技術大佬”&#xff0c;更是“問題解決者”1.1 架構師的分類&#xff1a;不止“開發架構師”一種1.2 架構師要關注什么&#xff1f;別只盯著技術1.3 架構師解決問題的4步心法&#xff1a;從定義到落地1.4 架構師的成長攻略&…

uniapp在微信小程序中實現 SSE 流式響應

前言 最近需要使用uniapp開發一個智能對話頁面&#xff0c;其中就需要使用SSE進行通信。 本文介紹下在uniapp中如何基于uni.request實現SSE流式處理。 在線體驗 #小程序:yinuosnowball SSE傳輸格式 返回輸出的流式塊: Content-Type為text/event-stream 每個流式塊均為 d…

STM32N6AI資料匯總

文章目錄前言一、STM32N6硬件資源1.1 NUCLEO-N657X0-Q1.2 STM32N6570-DK1.3 正點原子STM32N647二、STM32N6軟件資源2.1 STM32CubeN6例程資源包2.2 STM32圖像信號處理器&#xff08;ISP&#xff09;調優軟件2.3 正點原子N6開發板配套軟件三、AI軟件資源3.1 STM32N6 AI軟件包總結…

Flask學習筆記(一)

1、環境準備pip install Flask使用Flask開發第1個入門程序&#xff1a;from flask import Flask app Flask(__name__) app.route(/) def hello_world():return Hello, World!if __name__ __main__:app.run()Flask構造函數將當前模塊的名稱(__name__)作為參數。2、route函數ap…

CSP認證練習題目推薦(4)

思維、貪心、綜合 排隊打水 這道題目不算難&#xff0c;但是不注意還是會出現很多錯誤&#xff0c;比如結構體的書寫。以及自定義結構體排序。還有這里做的優化&#xff0c;使用前綴和記錄打水的等待時間&#xff0c;但是這里很容易出錯的點在于等待時間是應該是記錄的前一個…

MySQL 視圖的更新與刪除:從操作規范到風險防控

MySQL 視圖的更新與刪除&#xff1a;從操作規范到風險防控 視圖作為 “虛擬表”&#xff0c;其更新與刪除操作常常讓開發者困惑 ——“為什么更新視圖會報錯&#xff1f;”“刪除視圖會不會弄丟數據&#xff1f;” 實際上&#xff0c;80% 的視圖操作問題都源于對 “視圖依賴基表…

C 語言實現 I.MX6ULL 點燈(續上一篇)、SDK、deep及bsp工程管理

目錄 一、匯編點燈轉 C 語言實現 1. 關鍵字&#xff1a;volatile 2. 寄存器地址定義&#xff08;兩種方式&#xff09; &#xff08;1&#xff09;直接宏定義地址 &#xff08;2&#xff09;結構體封裝寄存器&#xff08;優化訪問&#xff09; 3. 核心功能代碼 &#xff…

DevOps實戰(7) - 使用Arbess+GitPuk+sourcefare實現Node.js項目自動化部署

Arbess 是一款國產開源免費的 CI/CD 工具&#xff0c;工具支持一鍵部署&#xff0c;頁面簡潔易用。本文將詳細介紹如何安裝配置使用GitPuk、sourcefare、Arbess系統&#xff0c;使用流水線拉取GitPuk源碼、使用sourcefare代碼掃描、構建安裝包并進行主機部署。 1、GitPuk 安裝…

算法,蒜鳥蒜鳥-P1-理解“雙指針”

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 有很多很多不足的地方&#xff0c;歡迎評論交流&#xff0c;感謝您的閱讀和評論&#x1f604;。 目錄引言1 雙指針&#xff1a;Two Pointers1.1 左右指…

使用cookiecutter創建python項目

一、關于Python項目結構Python 項目并沒有完全統一的 “固定結構”&#xff0c;但行業內有一些廣泛遵循的約定俗成的目錄結構&#xff08;尤其針對可分發的包或大型項目&#xff09;。同時&#xff0c;確實有工具可以快速生成這些標準化結構&#xff0c;提高開發效率&#xff0…

臺積電生態工程深度解析:從晶圓廠到蜂巢的系統架構遷移

當半導體巨頭將工廠視為生態系統&#xff0c;用工程思維解決環境問題概述&#xff1a;生態系統的工程化再造臺積電近日開展的"積蜜"項目絕非簡單的企業CSR行為&#xff0c;而是一場將生態系統視為復雜系統進行工程化改造的技術實踐。本文將從系統架構、數據監控、循環…

從零實現一個簡易計算器

最近在刷算法題時&#xff0c;遇到了實現計算器的問題。一開始覺得很簡單&#xff0c;但真正動手實現時才發現其中有很多細節需要考慮。今天就來分享一下我的實現思路和學到的經驗。問題分析我們需要實現一個能夠處理加減乘除四則運算的計算器&#xff0c;要正確處理運算符的優…

Actix-webRust Web框架入門教程

文章目錄引言Actix-web是什么&#xff1f;準備工作你的第一個Actix-web應用理解代碼結構處理請求和響應接收請求數據返回響應中間件 - 增強你的應用狀態管理和依賴注入實用示例&#xff1a;構建RESTful API測試你的Actix-web應用部署Actix-web應用結語額外資源引言 嘿&#xf…

若依框架前端通過 nginx docker 鏡像本地運行

1. 前言 項目運行過程圖&#xff1a;對于前端項目通過命令 npm run build 打包后&#xff0c;無法直接運行。存在如下錯誤&#xff1a;可以通過配置 nginx 服務器運行前端項目解決如上問題。 2. Nginx 運行 采用 docker 鏡像的方式運行&#xff0c;docker-compose.yml 文件內容…

淺聊一下HTTP協議

在日常上網瀏覽網頁、刷視頻時&#xff0c;背后都離不開 HTTP 協議的支持。作為 Web 世界的 “交通規則”&#xff0c;它負責服務器和客戶端瀏覽器之間的數據傳輸。這篇文章就帶大家全面了解 HTTP 協議&#xff0c;從基本概念到通信細節&#xff0c;再到安全相關的 HTTPS&#…

機器人控制器開發(定位——cartographer ros2 使用2)

文章總覽 1 純定位模式 當完成建圖后&#xff0c;會生成pbstream格式的地圖文件 配置純定位模式的lua腳本 backpack_2d_localization.lua include "backpack_2d.lua"TRAJECTORY_BUILDER.pure_localization_trimmer {max_submaps_to_keep 3, } POSE_GRAPH.optimi…

《大數據之路1》筆記3:數據管理

一 元數據 1.1 元數據概述 定義&#xff1a; 元數據是關于數據的數據&#xff0c;元數據打通了源數據、數據倉庫、數據應用&#xff0c;記錄了數據從生產到消費的全部過程。元數據主要記錄數據倉庫中模型的定義、各層級間的映射關系、監控數據倉庫的數據狀態和ETL的任務運行狀態…

排序實現java

排序算法概述Java中實現排序可以通過多種方式&#xff0c;包括內置方法、自定義算法或使用第三方庫。常見的排序算法有冒泡排序、選擇排序、插入排序、快速排序、歸并排序等。使用Arrays.sort()方法對于數組排序&#xff0c;Java提供了Arrays.sort()方法&#xff0c;支持對基本…

51c大模型~合集182

我自己的原文哦~ https://blog.51cto.com/whaosoft/14174587 #LaV-CoT 超越GPT-4o&#xff0c;螞蟻集團與南洋理工大學提出&#xff1a;首個語言感知的視覺思維鏈 隨著大型視覺語言模型&#xff08;VLM&#xff09;的飛速發展&#xff0c;它們在處理復雜的視…

C++ STL之deque的使用和模擬實現

目錄 deque 核心本質與定位 與stack和queue的關系: deque的使用 deque的底層實現 deque的原理介紹 deque的缺陷 總結: deque deque文檔 : deque 翻譯: 雙端隊列 deque&#xff08;通常發音類似“deck”&#xff09;是“double-ended queue”&#xff08;雙端隊列&…