日韩性视频-久久久蜜桃-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请求_前端数据请求的终极方案的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 久久男女视频 | 亚洲国产丝袜 | 香蕉视频免费网站 | 老湿机69福利 | 极品福利视频 | 无套内谢老熟女 | 久久久婷 | 超碰免费观看 | 精产国产伦理一二三区 | 电家庭影院午夜 | 久久成人18免费观看 | 韩日精品中文字幕 | 亚洲第一大网站 | 韩国精品在线观看 | 日韩wwww| 成人精品国产 | sm国产在线调教视频 | 久久综合激情网 | 欧美性生活一区二区 | 久久综合鬼色 | 国产情侣在线播放 | 香蕉视频亚洲一级 | 国产精品二区在线 | 深夜精品福利 | 91大神久久 | 五月天av影院 | 欧美激情久久久 | 韩国毛片一区二区 | 波多野 在线 | 精品熟女一区二区三区 | 久久久久久黄色 | 色姑娘综合 | 91猎奇在线观看 | 亚洲国产精品成人午夜在线观看 | 欧美激情片一区二区 | 美女黄色免费网站 | 国产精品vip | www.国产.com| 爱搞逼综合网 | 婷婷亚洲五月色综合 | 国产一线二线在线观看 | 久久只有精品 | 日韩欧美一区二区三区四区五区 | 国产资源精品 | 色吧久久 | 乱熟女高潮一区二区在线 | 加勒比av在线播放 | 影音先锋色小姐 | 夜夜爱视频 | 婷婷综合视频 | 国产粉嫩呻吟一区二区三区 | 亚洲码视频 | 成人免费无码大片a毛片抽搐色欲 | 亚洲图片欧美日韩 | 91精品免费在线观看 | 四虎网址在线观看 | 久久久99久久 | 免费激情av | 欧美视频xxx | 一级视频片 | 91久久精品一区二区 | 鲁一鲁av | 国产精品国产三级国产aⅴ下载 | 1024香蕉视频| 久久久久久久久蜜桃 | 麻豆爱爱 | 久久久久无码精品国产sm果冻 | 欧美日韩在线a | xxxx性视频 | 亚洲涩综合 | 精品亚洲成人 | 男人和女人日批视频 | 国产乱色 | 久久久久99精品成人片三人毛片 | 一级特黄a| 人人干av| 欧洲一区二区 | 丰满多毛的大隂户视频 | 久久亚洲精品小早川怜子 | 亚洲一区二区福利视频 | 午夜精品久久久久 | 亚州激情 | 色呦呦在线看 | 性久久久久久久久 | 夜夜嗨影院 | 中文天堂 | 麻豆影视国产在线观看 | 97狠狠干 | 丰满放荡岳乱妇91ww | 美国av一区二区 | 99草视频| 久久av网站 | 久久五月婷| 亚洲av无码国产在丝袜线观看 | 欧美粉嫩videosex极品 | 插插插操操操 | 超碰人人91 | 三年大全国语中文版免费播放 | 免费黄av|