摘要:原文載于我的博客這里主要探討一下怎么把數(shù)據(jù)請(qǐng)求從業(yè)務(wù)代碼中抽象出來。這種操作比前面的方式顯然上升了一個(gè)層面。這是非常好的準(zhǔn)備使用觀察者模式的場景。注意直接這個(gè)詞,不考慮請(qǐng)求的意思是說未來的前端沒有代碼層面的,只需要拿數(shù)據(jù),只需要拿數(shù)據(jù)。
原文載于我的博客 http://www.tangshuang.net/381...
這里主要探討一下怎么把數(shù)據(jù)請(qǐng)求從業(yè)務(wù)代碼中抽象出來。
傳統(tǒng)的數(shù)據(jù)請(qǐng)求方式是我們?cè)诰唧w的業(yè)務(wù)代碼,或某些特定的邏輯代碼(例如redux的action)中手工寫一個(gè)ajax,無論是使用最新的fetch api,還是使用axios,都是在直接構(gòu)建一個(gè)請(qǐng)求發(fā)送器和控制請(qǐng)求過程。當(dāng)然,這是比較容易理解的,任何人多帶帶看這段代碼都能讀懂。
但是在很多項(xiàng)目中,請(qǐng)求往往都越來越固定,總的和backend打交道的api估計(jì)不超過20個(gè),所以我們嘗試把所有的請(qǐng)求封裝在一個(gè)services文件夾里面,形成一個(gè)獨(dú)立的module,請(qǐng)求某個(gè)數(shù)據(jù)的時(shí)候,我們調(diào)用這個(gè)module的某個(gè)api。這種操作比前面的方式顯然上升了一個(gè)層面。
但是,我們會(huì)遇到問題。當(dāng)應(yīng)用中的兩段代碼,同時(shí)使用了一個(gè)service,如果不加處理,就會(huì)導(dǎo)致同一個(gè)頁面,同一時(shí)間,對(duì)一個(gè)backend api發(fā)出兩個(gè)相同的請(qǐng)求。這種情況在我之前的項(xiàng)目中經(jīng)常出現(xiàn):一個(gè)頁面里面有兩個(gè)組件的實(shí)例。之前想到了使用cache,當(dāng)一個(gè)請(qǐng)求發(fā)出的時(shí)候,發(fā)現(xiàn)參數(shù)都沒變,那么直接把cache的數(shù)據(jù)返回好了,這樣還可以提高數(shù)據(jù)請(qǐng)求的性能。然而,這完全沒有解決掉問題,因?yàn)楫?dāng)?shù)谝淮螖?shù)據(jù)請(qǐng)求的時(shí)候,cache是沒有的,兩個(gè)請(qǐng)求還是會(huì)同時(shí)發(fā)出。后來想到,把這請(qǐng)求的promise緩存起來,當(dāng)?shù)谝粋€(gè)請(qǐng)求發(fā)出之后,第二個(gè)請(qǐng)求準(zhǔn)備發(fā)之前,先去檢查cache列表中存不存在同請(qǐng)求的promise,如果存在,直接返回這個(gè)promise,這樣,當(dāng)這個(gè)promise成功的時(shí)候,兩個(gè)地方的then都被觸發(fā)了。
接下來,我們發(fā)現(xiàn)還有另外一種需求,當(dāng)一個(gè)頁面里面同一個(gè)組件渲染了兩個(gè)實(shí)例的時(shí)候,一個(gè)實(shí)例請(qǐng)求到新數(shù)據(jù),我們還希望另一個(gè)實(shí)例也可以得到這個(gè)數(shù)據(jù),至于是否刷新界面,可以由程序來決定。這是非常好的準(zhǔn)備使用觀察者模式的場景。
觀察者模式,簡單的說,就是“訂閱-分發(fā)”模式,觀察者(訂閱者)subscribe一個(gè)或多個(gè)特定訂閱,當(dāng)被訂閱的內(nèi)容發(fā)生變化時(shí),發(fā)布者便把這些變化分發(fā)給訂閱者。之所以叫觀察者,是因?yàn)楫?dāng)觀察者本身并不做任何和訂閱內(nèi)容相關(guān)的工作,只處于一個(gè)干自己的事,但是時(shí)時(shí)刻刻盯著自己訂閱的內(nèi)容,一旦收到訂閱通知時(shí),馬上干對(duì)應(yīng)的事。
上面的場景就是這樣一種場景。我們需要獨(dú)立出一個(gè)觀察者,這就是datamanager,它接受來自頁面內(nèi)兩個(gè)實(shí)例的訂閱,當(dāng)其中一個(gè)訂閱者通過datamanager的api觸發(fā)了數(shù)據(jù)請(qǐng)求,導(dǎo)致兩個(gè)實(shí)例訂閱的相同內(nèi)容發(fā)生改變時(shí),datamanager將新的內(nèi)容同時(shí)分發(fā)給這兩個(gè)實(shí)例。
看上去非常簡單的邏輯,實(shí)現(xiàn)起來卻不那么簡單。索性你可以通過這里直接閱讀源碼來了解我是怎么實(shí)現(xiàn)的。
使用datamanager也很簡單:
npm install --save datamanager.js
然后在你的代碼中使用它:
import DataManager from "datamanager.js" const datamanager = new DataManager() datamananger.register([ ...datasources ]) // datasource請(qǐng)閱讀文檔 datamanager.subscribe("datasourceId", (data) => { // 這里可以執(zhí)行ComponentB的重新渲染動(dòng)作 })
在另外的代碼中可以通過request來獲取數(shù)據(jù):
// ComponentA里面執(zhí)行 async () => { let data = await datamanager.request("datasourceId") // 當(dāng)數(shù)據(jù)回來時(shí),上面的subscribe里的回調(diào)函數(shù)會(huì)被執(zhí)行 // 用data做點(diǎn)事 }
datamanager提供來subscribe來進(jìn)行訂閱,只需要在subscribe的第二個(gè)參數(shù)中告訴datamanager,對(duì)應(yīng)的datasourceId數(shù)據(jù)回來之后,自己要做什么就可以了。
回頭再來看datamanager,你就發(fā)現(xiàn),它不需要你告訴單次請(qǐng)求的url,而是把url通過datasource注冊(cè)進(jìn)去,它的本意就是,這個(gè)datasource可能會(huì)反復(fù)使用,因此你只需要記住它的id即可。這和我們傳統(tǒng)的request就開始有些不同了。
request方法是完全按照傳統(tǒng)請(qǐng)求返回promise的思想設(shè)計(jì)的,真正的datamanager的思想精髓,是在于它提供的get方法,當(dāng)你熟悉datamanager的操作之后,開始使用get方法,而完全忘掉request方法的時(shí)候,你會(huì)發(fā)現(xiàn),datamanager中完全沒有數(shù)據(jù)請(qǐng)求的概念。它提供了一種新的思路:對(duì)于一個(gè)應(yīng)用,和backend api打交道的部分被抽象出來,應(yīng)用只從datamanager獲取數(shù)據(jù),而不關(guān)心它是怎么從backend拿到數(shù)據(jù)的。
對(duì)于應(yīng)用而言,datamanager就在那里,你通過register注冊(cè)datasource之后,就只管找它要數(shù)據(jù)就是了,要數(shù)據(jù),給數(shù)據(jù),要數(shù)據(jù),給數(shù)據(jù)。后端?我不管你怎么從后端拿數(shù)據(jù),反正我只知道數(shù)據(jù)應(yīng)該在你那里。它就像一個(gè)data center,管理著前端數(shù)據(jù)。但同時(shí),它又是observer,為實(shí)現(xiàn)數(shù)據(jù)在不同實(shí)例間的實(shí)時(shí)共享提供了便利。
這里可以透露一下,datamanager內(nèi)部是用axios請(qǐng)求數(shù)據(jù),但是對(duì)于開發(fā)者而言,不需要知道(還是需要知道axios的response結(jié)構(gòu)的,如果有需要的話)。當(dāng)然,這里需要說明的是,backend還是在的,只是你把backend的信息放到了datasource中,一次性注冊(cè)進(jìn)了datamanager。
總而言之,datamanager是對(duì)前端數(shù)據(jù)請(qǐng)求的一次提煉,這種提煉把前端負(fù)責(zé)的分散的數(shù)據(jù)請(qǐng)求代碼規(guī)整化,把datasource集中管理,在代碼中,不考慮請(qǐng)求這個(gè)動(dòng)作,而是從datamanager中直接拿一個(gè)數(shù)據(jù),拿到的是什么就是什么,不需要質(zhì)疑。注意“直接”這個(gè)詞,“不考慮請(qǐng)求”的意思是說“未來的前端沒有代碼層面的ajax”,只需要拿數(shù)據(jù),只需要拿數(shù)據(jù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92224.html
摘要:我們可以把取消發(fā)貨單和取消訂單看成一個(gè)被觀察或被訂閱的類實(shí)例的對(duì)象,一旦發(fā)生取消行為,我們立即通知各個(gè)觀察者做出相對(duì)應(yīng)的行為。裝飾器模式裝飾器思想,不管以前業(yè)務(wù)邏輯,甚至不去讀,調(diào)用之前的接口裝飾上新的數(shù)據(jù),達(dá)到自己的目的。 前言 還是每月的目標(biāo)至少寫一篇文章,一晃八月份就要過去了,這個(gè)月依然沒有什么產(chǎn)出,毫無疑問最近的狀態(tài)就是不停的工作,不停的加班。所以還是把最近工作進(jìn)行一個(gè)總結(jié),首...
摘要:前言原本說接下來會(huì)專注學(xué)但是最新工作又學(xué)習(xí)了一些有意思的庫於是就再寫下來做個(gè)簡單的入門之前我寫過一篇文章這個(gè)也算是作為一個(gè)補(bǔ)充吧這次無非就是類似筆記把認(rèn)為的一些關(guān)鍵點(diǎn)記下來有些地方還沒用到就衹是描述一下代碼有些自己寫的有些文檔寫的很好就搬下 前言 原本說接下來會(huì)專注學(xué)nodejs,但是最新工作又學(xué)習(xí)了一些有意思的庫,於是就再寫下來做個(gè)簡單的入門,之前我寫過一篇文章,這個(gè)也算是作為一個(gè)補(bǔ)...
摘要:前言初衷以系列故事的方式展現(xiàn)源碼邏輯,盡可能以易懂的方式講解源碼本系列文章用故事解讀源碼一用故事解讀源碼二用故事解讀源碼三用故事解讀源碼四裝飾器和用故事解讀源碼五文章編排每篇文章分成兩大段,第一大段以簡單的偵探系列故事的形式講解所涉及人物場 ================前言=================== 初衷:以系列故事的方式展現(xiàn) MobX 源碼邏輯,盡可能以易懂的方式...
摘要:上一篇我們講到了關(guān)于行為樹的內(nèi)存優(yōu)化,這一篇我們將講述行為樹的另一種優(yōu)化方法基于事件的行為樹。而函數(shù)負(fù)責(zé)將行為壓入隊(duì)列首端,節(jié)點(diǎn)則負(fù)責(zé)設(shè)置行為執(zhí)行狀態(tài)并顯示調(diào)用監(jiān)察函數(shù)。 上一篇我們講到了關(guān)于行為樹的內(nèi)存優(yōu)化,這一篇我們將講述行為樹的另一種優(yōu)化方法——基于事件的行為樹。 問題 在之前的行為樹中,我們每幀都要從根節(jié)點(diǎn)開始遍歷行為樹,而目的僅僅是為了得到最近激活的節(jié)點(diǎn),既然如此,為什么我們...
摘要:發(fā)布訂閱現(xiàn)在每個(gè)人應(yīng)該都用微信吧,一個(gè)人可以關(guān)注多個(gè)公眾號(hào),多個(gè)人可以同時(shí)關(guān)注相同的公眾號(hào)。公眾號(hào)每周都會(huì)更新內(nèi)容,并推送給我們,把寫好的文章在微信管理平臺(tái)更新就好了,點(diǎn)擊推送,就相當(dāng)于發(fā)布。 什么是MVVM MVVM——Model-View-ViewModle的縮寫,MVC設(shè)計(jì)模式的改進(jìn)版。Model是我們應(yīng)用中的數(shù)據(jù)模型,View是我們的UI層,通過ViewModle,可以把我們M...
閱讀 2228·2019-08-30 15:54
閱讀 1964·2019-08-30 13:49
閱讀 683·2019-08-29 18:44
閱讀 836·2019-08-29 18:39
閱讀 1119·2019-08-29 15:40
閱讀 1540·2019-08-29 12:56
閱讀 3155·2019-08-26 11:39
閱讀 3107·2019-08-26 11:37