日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

options请求_前端数据请求的终极方案

發布時間:2024/1/23 HTML 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 options请求_前端数据请求的终极方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數據請求是我們開發中非常重要的一環,如何優雅地進行抽象處理,不是一件很容易的事情,也是經常被忽略的事情,處理不好的話,重復的代碼散落在各處,維護成本極高。

所以我們需要好好梳理下數據請求涉及到哪些方面,對它有整體的管控,從而設計出擴展性高的方案。

案例分析

下面我們以 axios 這個請求庫進行講解。

假如我們在頁面中發出一個 POST 請求,類似這樣:

axios.post('/user/create', { name: 'beyondxgb' }).then((result) => {// do something });

后來發現需要防止 CSRF,那我們需要在請求中的 headers 加上 X-XSRF-TOKEN,所以變成這樣:

axios.post('/user/create', { name: 'beyondxgb' }, {headers: {'X-XSRF-TOKEN': 'xxxxxxxx',}, }).then((result) => {// do something });

這時可以發現,難道每次發起 post 請求都需要這樣配置嗎?所以會想到把這部分配置抽離出來,抽象出類似這樣一個方法:

function post(url, data, config) {return axios.post(url, data, {headers: {'X-XSRF-TOKEN': 'xxxxxxxx',},...config,}); }

所以我們需要對參數配置進行抽象。

到了測試流程的時候,發現服務端的請求不是總返回成功的,那怎么辦?那就 catch 處理一下:

post('/user/create', { name: 'beyondxgb' }).then((result) => {// do something }).catch((error) => {// deal with error// 200// 503// SESSION EXPIRED// ... });

寫下來總感覺哪里不對啊,原來請求錯誤有這么多情況,我整個項目有很多請求數據的地方呢,這部分代碼肯定是通用的,抽象出來!

function dealWithRequestError(error) {// deal with error// 200// 503// SESSION EXPIRED// ... } function post(url, data, config) {return axios.post(url, data, {headers: {'X-XSRF-TOKEN': 'xxxxxxxx',},...config,}).catch(dealWithRequestError); }

所以我們需要對異常處理進行抽象。

項目上線前業務方可能提出穩定性的需求,這時我們需要對請求進行監控,把接口請求成功和失敗的情況都記錄下來。同樣,我們把這部分代碼也要寫到公用的地方,類似這樣:

function post(url, data, config) {return axios.post(url, data, {headers: {'X-XSRF-TOKEN': 'xxxxxxxx',},...config,}).then((result) => {// 記錄成功情況...return result;}).catch((error) => {// 記錄失敗情況...return dealWithRequestError(error);); }

所以我們需要對請求監控進行抽象。

方案設計

從上面對一個簡單的 post 請求的案例分析中,我們可以看到,數據請求主要涉及三方面 參數配置、異常處理 和 請求監控。上面例子的處理還是比較粗糙,整體上還是需要進行代碼組織和分層。

參數配置

首先,我們處理下參數的配置,上面的例子只是對 post 請求作了分析,其實對于其他比如 get,put 都一樣的,我們可以對這些請求作統一的處理。

request.js

import axios from 'axios';// The http header that carries the xsrf token value { X-XSRF-TOKEN: '' } const csrfConfig = {'X-XSRF-TOKEN': '', }; // Build uniform request async function buildRequest(method, url, params, options) {let param = {};let config = {};if (method === 'get') {param = { params, ...options };} else {param = JSON.stringify(params);config = {headers: {...csrfConfig,},};config = Object.assign({}, config, options);}return axios[method](url, param, config); }export const get = (url, params = {}, options) => buildRequest('get', url, params, options); export const post = (url, params = {}, options) => buildRequest('post', url, params, options);

這樣的話,我們對外就暴露出 get 和 post 的方法,其他請求類似,在此只用 get 和 post 作為示例,入參分別是 API地址,數據 和 擴展配置。

異常處理

其實異常處理場景會比較復雜,不是簡單地 catch 一下,往往伴隨著業務邏輯和UI的交互,異常主要有兩方面,全局異常和業務異常。

全局異常,也可以說是通用的異常,比如服務端返回503,網絡異常,登錄失效,無權限等,這些異常是可以預料并可控的,只要和服務端約定好格式,捕獲下異常再展示出來即可。

業務異常,指的是和業務邏輯緊密相關的,比如提交失敗,數據校驗失敗等,這些異常往往每個接口有不一樣的情況,而且需要個性化展示錯誤,所以這部分可能不能進行統一處理,有時候需要把展示錯誤交到 View 層去實現。

在實現上,我們不會直接在上面的請求方法中直接 catch,而是利用 axios 提供的 interceptors 功能,這樣可以將異常的處理和核心的請求方法隔離出來,畢竟這部分是要和 UI 進行交互的。我們來看看如何實現:

error.js

import axios from 'axios';// Add a response interceptor axios.interceptors.response.use((response) => {const { config, data } = response;// 和服務端約定的 Codeconst { code } = data;switch (code) {case 200:return data;case 401:// 登錄失效break;case 403:// 無權限break;default:break;}if (config.showError) {// 接口配置指定需要個性化展示錯誤return Promise.reject(data);}// 默認展示錯誤// ... Toast error }, (error) => {// 通用錯誤if (axios.isCancel(error)) {// Request cancel} else if (navigator && !navigator.onLine) {// Network is disconnect} else {// Other error}return Promise.reject(error); });

axios 的 interceptors 功能,其實就是一個鏈式調用,可以在請求前和請求后做事情,這里我們在請求后進行攔截處理,對返回的數據進行校驗和捕獲異常,對于通用的錯誤我們直接通過 UI 交互將錯誤展示出來,對于業務上的錯誤我們檢查下接口有沒有配置說要個性化展示錯誤,如果有的話,將錯誤處理交給頁面,如果沒有的話,進行錯誤兜底處理。

請求監控

請求監控這塊和異常處理類似,只不過這里只是記錄情況,不涉及到 UI 上的交互或者和業務代碼的交互,所以可以把這部分邏輯直接寫在異常處理那里,或者在請求后再添加一個攔截器,單獨處理。

monitor.js

axios.interceptors.response.use((response) => {const { status, data, config } = response;// 根據返回的數據和接口參數配置,對請求進行埋點 }, (error) => {// 根據返回的數據和接口參數配置,對請求進行埋點 });

比較建議這樣做,保持每個模塊獨立,符合單一功能原則(SRP)。

好了,到現在為止,參數配置、異常處理 和 請求監控 都設計完了,有三個文件:

  • request.js:請求庫配置,對外暴露出 get,post 方法。
  • error.js:請求的一些異常處理,涉及到和外面對接的是該接口是否需要個性化展示錯誤。
  • monitor.js:請求的情況記錄,比較獨立的一塊。

那在頁面上調用的時候可以這樣子:

import { get, post } from 'request.js';get('/user/info').then((data) => {}); post('/user/update', { name: 'beyondxgb' }, { showError: true }).then((data) => {if (data.code !== 200) {// 展示錯誤} else {// do something} });

再仔細思考下,覺得還不是最完美的,API 名稱直接在頁面上引用,這樣會給自己埋坑,如果后面 API 名稱改了,而且這個 API 在多個頁面被調用,那維護成本就高了。我們有兩種方法,第一種就是將所有 API 獨立配置在一個文件中,給頁面去讀取,第二種辦法就是我們在請求庫和頁面之前再加一層,叫 service,也就是所謂的服務層,對外暴露接口方法給頁面,這樣頁面完全不需要關注接口是什么或者接口是如何取數據的,而且以后接口的任何修改,只要在服務層進行修改即可,對頁面沒有任何影響。

當然我是采取第二種方法,類似這樣子:

services.js

import { get, post } from 'request.js';// fetch random data export async function fetchRandomData(params) {return get('https://randomuser.me/api', params); }// update user info export async function updateUserInfo(params, options) {return post('/user/info', params, { showError: true, ...options }); }

這樣子的話,頁面就不會直接和請求庫進行交互,而是跟服務層獲取對應的方法。

import { fetchRandomData, updateUserInfo } from 'services.js';fetchRandomData().then((data) => {}); updateUserInfo({ name: 'beyondxgb' }).then((data) => {if (data.code !== 200) {// 展示錯誤} else {// do something} });

我們來看看最終的方案是這樣子的:

延伸擴展

上面講的都是以 axios 這個請求庫為例,其實思想是互通的,換一個請求庫也是一樣的處理的方法。不知大家有沒有注意到,把請求庫參數配置和異常處理兩個模塊獨立出來,完全是利用了 interceptors 的特性,這也是我喜歡 axios 的原因之一,我覺得這個設計得很好,類似中間件的做法,在請求數據到達頁面之前,我們可以通過寫攔截器對數據進行過濾、加工、校驗、異常監控等。

我覺得任何一個請求庫都可以實現這個功能,就算請求庫是有歷史包袱,也可以自己在外面包一層。比如說有請求庫 abc,它有一個 request 方法,可以這樣復寫它:

import abc from 'abc';function dispatchRequest(options) {const reqConfig = Object.assign({}, options);return abc.request(reqConfig).then(response => ({response,options,})).catch(error => (Promise.reject({error,options,}))); }class Request {constructor(config) {this.default = config;this.interceptors = {request: new InterceptorManager(),response: new InterceptorManager(),};} }Request.prototype.request = function request(config = {}) {// Add interceptorsconst chain = [dispatchRequest, undefined];let promise = Promise.resolve(options);// Add request interceptorsthis.interceptors.request.forEach((interceptor) => {chain.unshift(interceptor.fulfilled, interceptor.rejected);});// Add response interceptorsthis.interceptors.response.forEach((interceptor) => {chain.push(interceptor.fulfilled, interceptor.rejected);});while (chain.length) {promise = promise.then(chain.shift(), chain.shift());}return promise; };

更多

前面我們很好地解決了數據請求的問題,還有另一方面,也是和數據請求緊密相關的,就是數據模擬(Mock) 了,在項目開發前期服務端沒有準備好數據之前,我們只有自己在本地進行 Mock 數據了,或者很多公司已經有比較好的平臺實現這個功能了,我這里介紹下不借助平臺,只是在本地啟動一個小工具即可實現 Mock 數據。

這里我自己寫了一個小工具 @ris/mock,只要把它作為中間件注入到 webpack-dev-server 中就好了。

webpack.config.js

const mock = require('@ris/mock');module.exports = {//...devServer: {compress: true,port: 9000,after: (app) => {// Start mock datamock(app);},} };

這時候在項目根目錄建立 mock 文件夾,文件夾里建一個 rules.js 文件,rules.js 里面配置的是接口的映射規則,類似這樣子:

module.exports = {'GET /api/user': { name: 'beyondxgb' },'POST /api/form/create': { success: true },'GET /api/cases/list': (req, res) => { res.end(JSON.stringify([{ id: 1, name: 'demo' }])); },'GET /api/user/list': 'user/list.json','GET /api/user/create': 'user/create.js', };

配置規則后,請求接口的時候,就會被轉發,轉發的時候可以是一個 對象,函數,文件,詳細使用可以參考文檔。

結語

在數據請求方案的設計中,也證實了我們的“寫代碼”是“程序設計”,而不是“程序編寫”,我們要對自己的代碼負責,如何讓自己的代碼可維護性高,易擴展,是優秀工程師的基本素養。

以上的方案已沉淀在 RIS 中,包含代碼組織結構和技術實現,可以初始化一個 Standard 應用看看,之前的文章《RIS,創建 React 應用的新選擇》 有簡單提過,歡迎大家體驗。

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的options请求_前端数据请求的终极方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 肉色超薄丝袜脚交一区二区 | 成人av影视在线观看 | 精品伦理一区二区 | 日本韩国欧美一区二区 | 欧洲成人av | 日韩黄色大片 | 毛片一级片 | 国产视频一区二区三 | 日少妇的逼 | 日韩精品中文在线 | 国产按摩一区二区三区 | 老牛影视少妇在线观看 | 波多野结衣一二区 | 欧美日韩一区二区在线播放 | 国产乱色精品成人免费视频 | 国产精品久久久久野外 | 秋霞福利 | 婷婷久久五月 | 国产视频污| 最新久久 | 最近更新中文字幕 | 国产视频二 | 五月婷在线观看 | 国产成人精品视频在线观看 | 男女午夜视频 | 美女扒开粉嫩的尿囗给男生桶 | 久草免费资源站 | 18av在线视频 | 久久99精品国产91久久来源 | 亚洲激情视频网站 | 久久99精品久久久久久噜噜 | 国产欧美一区二区在线 | 国精产品一区二区三区 | 日本伦理一区 | 91久久精品一区二区三 | 狠狠操狠狠操 | 欧美男女性生活视频 | 亚欧在线观看 | 日韩中文字幕免费 | 欧美性做爰猛烈叫床潮 | 激情开心网站 | av成人精品| 一区二区色 | 伊人影院网 | 依人在线视频 | 福利小视频 | 91精品国产色综合久久不卡98口 | 亚洲videos| av视| 男男做爰猛烈叫床爽爽小说 | 漂亮人妻被黑人久久精品 | av导航网址| 国产91久| 二区三区av| 久久99精品久久久久婷婷 | 久久久一区二区 | wwww欧美 | 久久久久久国产精品免费 | 欧美一区二区三区成人久久片 | 日本一区二区三区在线免费观看 | 精品一区二区免费视频 | 成年人三级视频 | 黄色不雅视频 | 波多野结衣欲乱上班族 | 日本人妖japanesexxx | 日韩高清一级 | 在线免费看91 | 亚洲精品高清视频 | 粉嫩av一区二区三区免费观看 | 国产在线精品成人欧美 | 性av免费 | 蜜桃成人无码区免费视频网站 | 欧美午夜精品一区二区三区 | 欧美国产视频一区 | 亚洲www视频 | 很污的网站| 老太婆av| 久久久久久久成人 | 乳色吐息在线看 | 国产精品久久久久久久久免费 | 极品久久久 | 亚洲精品国产免费 | 日本一级做a爱片 | 色偷偷欧美| 亚洲a成人 | 国产精品呻吟久久 | 女同中文字幕 | 粗了大了 整进去好爽视频 日本女优中文字幕 | 香蕉视频亚洲一级 | 伊人动漫 | 韩国美女黄色片 | 超碰caopor| av五十路 | 日本美女三级 | wwwyoujizz日本| 亚洲小说区图片区 | 欧美裸体xxxx极品少妇 | 免费黄色链接 | 国产精品久久久久久亚洲毛片 |