Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
個(gè)留言剛看到:
之前給大家分享過(guò)一個(gè)文章《只要是屏蔽網(wǎng)線,都應(yīng)該做接地,否則屏蔽線就會(huì)失去應(yīng)有的意義》實(shí)際上就是說(shuō)如何給屏蔽線接地的。
iN的做法很簡(jiǎn)單——直接從接線板上引出一根地線,再懟到交換機(jī)上面的接地端子上:
當(dāng)時(shí)用了地線連接線,
弱電箱里面的接線板打開(kāi)后可以看到三個(gè)接線柱。
地線連接線直接擰到接線板的地線接線柱上,
另一端擰到設(shè)備的地線端子上。
這時(shí)候,就有很多大聰明得說(shuō)“弱電的接線地線不能接強(qiáng)電地線”
這件事其實(shí)就像回復(fù)里面的電工所說(shuō)的話一樣——瞎掰!
咱們看一個(gè)網(wǎng)絡(luò)交換機(jī)的拆解圖片:
注意一下左上角電源線的接線方式,你會(huì)發(fā)現(xiàn):
地線進(jìn)入交換機(jī)后被第一時(shí)間用一根螺絲擰在了交換機(jī)的外殼上。
同時(shí)我們?cè)倏春诵牡牡碾娐钒宀糠郑?/p>
我們會(huì)發(fā)現(xiàn)這臺(tái)交換機(jī)在電路板上利用金屬螺絲直接連接了電路板裸露在外的銅薄上。
這個(gè)銅薄就和地線相連了,同時(shí),電路板和地線連接的電路最終也會(huì)連接到RJ45接口上的接地簧片上
網(wǎng)線如果有屏蔽層并且使用屏蔽接頭的話,屏蔽接頭就會(huì)和這根簧片接觸,從而也是連接在了電源線上那根地線上。
在iN之前給大家指出的案例里面,只不過(guò)是吧那根地線從外面連接在了交換機(jī)的外殼上,而華為的交換機(jī)則是將地線從交換機(jī)的內(nèi)部連接在了外殼上。本質(zhì)上是沒(méi)有區(qū)別的。
所以——電工說(shuō)的“弱電不能接強(qiáng)電地”就有點(diǎn)太想當(dāng)然了。
那么問(wèn)題來(lái)了,家里的弱電如何接地?
當(dāng)然是按照iN的方式來(lái)接了。為啥iN的交換機(jī)沒(méi)有得這樣接地呢?
因?yàn)檫@款CSS610交換機(jī)是這樣供電的,交換機(jī)只能在電源端口取得直流電供給。并沒(méi)有被引入地線。所以這根地線咱們要手動(dòng)的加一下。
能不能不這樣加根外殼上的小尾巴呢?
那么就選擇帶有地線的交換機(jī)就好了,通常大一點(diǎn)的小交換機(jī)都支持220V帶地線的梅花插頭或者C13插頭的接入。
這種插頭大家應(yīng)該都見(jiàn)過(guò),基本上臺(tái)式機(jī)、電飯鍋什么的都會(huì)使用到,內(nèi)置電源的交換機(jī)大部分也是使用這種插頭。
使用這種線的結(jié)果就是——第一時(shí)間地線被從內(nèi)部接入到了外殼上。
當(dāng)然了,你如果既不想在直流供電的小交換機(jī)上接一個(gè)小尾巴,又不想安裝一個(gè)相對(duì)比較大的內(nèi)置電源的交換機(jī),那么還有一個(gè)選擇就是用機(jī)架。
沒(méi)錯(cuò),就是機(jī)架,如果你選用機(jī)架,并用螺絲將所有設(shè)備都固定在機(jī)架上,那么只要你的機(jī)架里面有一個(gè)設(shè)備是帶有電源接地的,那么所有的設(shè)備實(shí)際上就都接地了,這里有一個(gè)要點(diǎn)——你要用不帶漆膜的螺絲緊錮設(shè)備。
像上面這樣,為了好看用磷化發(fā)黑效果的螺絲去緊固設(shè)備,而且大多數(shù)設(shè)備都放在托盤上,這是沒(méi)有接地效果的。特別不推薦在機(jī)架上這樣搞。
如果這些都不愿意做,非得在不接地的情況下接通網(wǎng)絡(luò),那么最好的處理方式就是——?jiǎng)e用屏蔽電纜。
擎反指紋瀏覽器是一種旨在減少或隱藏用戶瀏覽器指紋識(shí)別的技術(shù)和工具。下面將通過(guò)文字和視頻的方式詳細(xì)介紹反指紋瀏覽器的相關(guān)內(nèi)容。
反指紋瀏覽器的原理和技術(shù)
反指紋瀏覽器的目標(biāo)是減少用戶瀏覽器指紋的唯一性,從而減少用戶的跟蹤風(fēng)險(xiǎn)。為了實(shí)現(xiàn)這一目標(biāo),反指紋瀏覽器使用了許多技術(shù)和工具,包括:
除了以上技術(shù)和工具之外,反指紋瀏覽器還可以使用一些其他的技術(shù)來(lái)減少用戶的指紋唯一性,比如使用虛擬機(jī)、使用 Tor 瀏覽器等等。
反指紋瀏覽器的應(yīng)用場(chǎng)景
反指紋瀏覽器可以被用于多種應(yīng)用場(chǎng)景,包括:
o B 業(yè)務(wù)的生命周期與迭代通常會(huì)持續(xù)多年,隨著產(chǎn)品的迭代與演進(jìn),以接口調(diào)用為核心的前后端關(guān)系會(huì)變得非常復(fù)雜。在多年迭代后,接口的任何一處修改都可能給產(chǎn)品帶來(lái)難以預(yù)計(jì)的問(wèn)題。在這種情況下,構(gòu)建更穩(wěn)健的前端應(yīng)用,保證前端在長(zhǎng)期迭代下的穩(wěn)健與可拓展性就變得非常重要。本文將重點(diǎn)介紹如何利用接口防腐策略避免或減少接口變更對(duì)前端的影響。
為了更清晰解釋前端面臨的難題,我們以 To B 業(yè)務(wù)中常見(jiàn)的儀表盤頁(yè)面為例,該頁(yè)面包含了可用內(nèi)存、已使用內(nèi)存和已使用的內(nèi)存占比三部分信息展示。
此時(shí)前端組件與接口之間的依賴關(guān)系如下圖所示。
當(dāng)接口返回結(jié)構(gòu)調(diào)整時(shí)MemoryFree 組件對(duì)接口的調(diào)用方式需要調(diào)整。同樣的,MemoryUsage 與 MemoryUsagePercent 也要進(jìn)行修改才能工作。
真實(shí)的 To B 業(yè)務(wù)面臨的接口可能會(huì)有數(shù)百個(gè),組件與接口的集成邏輯也遠(yuǎn)比以上的例子要復(fù)雜。
經(jīng)過(guò)數(shù)年甚至更長(zhǎng)時(shí)間的迭代后,接口會(huì)逐步產(chǎn)生多個(gè)版本,出于對(duì)界面穩(wěn)定性及用戶使用習(xí)慣的考量,前端往往會(huì)同時(shí)依賴接口的多個(gè)版本來(lái)構(gòu)建界面。當(dāng)部分接口需要調(diào)整下線或發(fā)生變更時(shí),前端需要重新理解業(yè)務(wù)邏輯,并做出大量代碼邏輯調(diào)整才能保證界面穩(wěn)定運(yùn)行。
常見(jiàn)的對(duì)前端造成影響的接口變更包括但不限于:
當(dāng)前端面對(duì)的是平臺(tái)型業(yè)務(wù)時(shí),此類問(wèn)題會(huì)變得更為棘手。平臺(tái)型產(chǎn)品會(huì)對(duì)一種或多種底層引擎進(jìn)行封裝,例如機(jī)器學(xué)習(xí)平臺(tái)可能會(huì)基于 TensorFlow、Pytorch 等機(jī)器學(xué)習(xí)引擎搭建,實(shí)時(shí)計(jì)算平臺(tái)可能基于 Flink、Spark 等計(jì)算引擎搭建。
雖然平臺(tái)會(huì)對(duì)引擎的大部分接口進(jìn)行上層封裝,但不可避免的仍然會(huì)有部分底層接口會(huì)直接被透?jìng)鞯角岸耍谶@個(gè)時(shí)候,前端不僅要應(yīng)對(duì)平臺(tái)的接口變更,還會(huì)面臨著開(kāi)源引擎接口的變更帶來(lái)的挑戰(zhàn)。
前端在面臨的困境是由獨(dú)特的前后端關(guān)系決定的。與其他領(lǐng)域不同,在 To B 業(yè)務(wù)中,前端通常以下游客戶的身份接受后端供應(yīng)商的供給,有些情況下會(huì)成為后端的跟隨者。
在客戶/供應(yīng)商關(guān)系中,前端處于下游,而后端團(tuán)隊(duì)處于上游,接口內(nèi)容與上線時(shí)間通常由后端團(tuán)隊(duì)來(lái)決定。
在跟隨者關(guān)系中,上游的后端團(tuán)隊(duì)不會(huì)去根據(jù)前端團(tuán)隊(duì)的需求進(jìn)行任何調(diào)整,前端只能去順應(yīng)上游后端的模型。這種情況通常發(fā)生在前端無(wú)法對(duì)上游后端團(tuán)隊(duì)施加影響的時(shí)刻,例如前端需要基于開(kāi)源項(xiàng)目的接口設(shè)計(jì)界面,或者是后端團(tuán)隊(duì)的模型已經(jīng)非常成熟且難以修改時(shí)。
《架構(gòu)整潔之道》的作者描述過(guò)這樣一個(gè)嵌入式架構(gòu)設(shè)計(jì)的難題,與上文我們描述的困境十分類似。
軟件應(yīng)當(dāng)是一種使用周期很長(zhǎng)的東西,而固件會(huì)隨著硬件的演進(jìn)而淘汰過(guò)時(shí),但事實(shí)上的情況是,雖然軟件本身不會(huì)隨著時(shí)間推移而磨損,但硬件及其固件卻會(huì)隨時(shí)間推移而過(guò)時(shí),隨即也需要對(duì)軟件做相應(yīng)的改動(dòng)。
無(wú)論是客戶/供應(yīng)商關(guān)系,還是跟隨者關(guān)系,正如軟件無(wú)法決定硬件的發(fā)展與迭代一樣,前端也很難或者無(wú)法決定引擎與接口的設(shè)計(jì),雖然前端本身不會(huì)隨著時(shí)間的推移而變得不可用,但技術(shù)引擎及相關(guān)接口卻會(huì)隨著時(shí)間推移而過(guò)時(shí),前端代碼會(huì)跟隨技術(shù)引擎的迭代更換逐步腐爛,最終難逃被迫重寫的命運(yùn)。
早在 Windows 誕生之前,工程師為了解決上文中硬件、固件與軟件的可維護(hù)性問(wèn)題,引入了 HAL(Hardware Abstraction Layer)的概念, HAL 為軟件提供服務(wù)并且屏蔽了硬件的實(shí)現(xiàn)細(xì)節(jié),使得軟件不必由于硬件或者固件的變更而頻繁修改。
HAL 的設(shè)計(jì)思想在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD) 中又被稱為防腐層(Anticorruption Layer)。在 DDD 定義的多種上下文映射關(guān)系中,防腐層是最具有防御性的一種。它經(jīng)常被使用在下游團(tuán)隊(duì)需要阻止外部技術(shù)偏好或者領(lǐng)域模型入侵的情況,可以幫助很好地隔離上游模型與下游模型。
我們可以在前端中引入防腐層的概念,降低或避免當(dāng)前后端的上下文映射接口變更對(duì)前端代碼造成的影響。
在行業(yè)內(nèi)有很多種方式可以實(shí)現(xiàn)防腐層,無(wú)論是近幾年大火的 GraphQL 還是 BFF 都可以作為備選方案,但是技術(shù)選型同樣受限于業(yè)務(wù)場(chǎng)景。與 To C 業(yè)務(wù)完全不同,在 To B 業(yè)務(wù)中,前后端的關(guān)系通常為客戶/供應(yīng)商或者跟隨者/被跟隨者的關(guān)系。在這種關(guān)系下,寄希望于后端配合前端對(duì)接口進(jìn)行 GraphQL 改造已經(jīng)變得不太現(xiàn)實(shí),而 BFF 的構(gòu)建一般需要額外的部署資源及運(yùn)維成本。
在上述情況下,在瀏覽器端構(gòu)建防腐層是更為可行的方案,但是在瀏覽器中構(gòu)建防腐層同樣面臨挑戰(zhàn)。
無(wú)論是 React、Angular 還是 Vue 均有無(wú)數(shù)的數(shù)據(jù)層解決方案,從 Mobx、Redux、Vuex 等等,這些數(shù)據(jù)層方案對(duì)視圖層實(shí)際上都會(huì)有入侵,有沒(méi)有一種防腐層解決方案可以與視圖層徹底解耦呢?以 RxJS 為代表的 Observable 方案在這時(shí)可能是最好的選擇。
RxJS 是 ReactiveX 項(xiàng)目的 JavaScript 實(shí)現(xiàn),而 ReactiveX 最早是 LINQ 的一個(gè)擴(kuò)展,由微軟的架構(gòu)師 Erik Meijer 領(lǐng)導(dǎo)的團(tuán)隊(duì)開(kāi)發(fā)。該項(xiàng)目目標(biāo)是提供一致的編程接口,幫助開(kāi)發(fā)者更方便的處理異步數(shù)據(jù)流。目前 RxJS 在開(kāi)發(fā)中經(jīng)常被作為響應(yīng)式編程開(kāi)發(fā)工具使用,但是在構(gòu)建防腐層的場(chǎng)景中,RxJS 代表的 Observable 方案同樣可以發(fā)揮巨大作用。
我們選擇 RxJS 主要基于以下幾點(diǎn)考慮:
當(dāng)在引入 RxJS 將所有類型的接口轉(zhuǎn)換為 Observable 對(duì)象后,前端的視圖組件將僅依賴 Observable,并與接口實(shí)現(xiàn)的細(xì)節(jié)解耦,同時(shí),Observable 可以與 Promise 相互轉(zhuǎn)換,在視圖層獲得的是單純的 Promise,可以與任意數(shù)據(jù)層方案和框架搭配使用。
除了轉(zhuǎn)換為 Promise 之外,開(kāi)發(fā)者也可以與 RxJS 在渲染層的解決方案,例如 rxjs-hooks 混用,獲得更好的開(kāi)發(fā)體驗(yàn)。
參照上文的防腐層設(shè)計(jì),我們?cè)陂_(kāi)頭的儀表盤項(xiàng)目中實(shí)現(xiàn)以 RxJS Observable 為核心的防腐層代碼。
其中防腐層的核心代碼如下
export function getMemoryFreeObservable(): Observable<number> {
return fromFetch("/api/v1/memory/free").pipe(mergeMap((res) => res.json()));
}
export function getMemoryUsageObservable(): Observable<number> {
return fromFetch("/api/v1/memory/usage").pipe(mergeMap((res) => res.json()));
}
export function getMemoryUsagePercent(): Promise<number> {
return lastValueFrom(forkJoin([getMemoryFreeObservable(), getMemoryUsageObservable()]).pipe(
map(([usage, free]) => +((usage / (usage + free)) * 100).toFixed(2))
));
}
export function getMemoryFree(): Promise<number> {
return lastValueFrom(getMemoryFreeObservable());
}
export function getMemoryUsage(): Promise<number> {
return lastValueFrom(getMemoryUsageObservable());
}
MemoryUsagePercent 的實(shí)現(xiàn)代碼如下,此時(shí)該組件將不再依賴具體的接口,而直接依賴防腐層的實(shí)現(xiàn)。
function MemoryUsagePercent() {
const [usage, setUsage] = useState<number>(0);
useEffect(() => {
(async () => {
const result = await getMemoryUsagePercent();
setUsage(result);
})();
}, []);
return <div>Usage: {usage} %</div>;
}
export default MemoryUsagePercent;
1 返回字段調(diào)整
返回字段變更時(shí),防腐層可以有效攔截接口對(duì)組件的影響,當(dāng) /api/v2/quota/free 與 /api/v2/quota/usage 的返回?cái)?shù)據(jù)變更為以下結(jié)構(gòu)時(shí)
{
requestId: string;
data: number;
}
我們只需要調(diào)整防腐層的兩行代碼,注意此時(shí)我們的上層封裝的 getMemoryUsagePercent 基于 Observable 構(gòu)建所以不需要進(jìn)行任何改動(dòng)。
export function getMemoryUsageObservable(): Observable<number> {
return fromFetch("/api/v2/memory/free").pipe(
mergeMap((res) => res.json()),
+ map((data) => data.data)
);
}
export function getMemoryUsageObservable(): Observable<number> {
return fromFetch("/api/v2/memory/usage").pipe(
mergeMap((res) => res.json()),
+ map((data) => data.data)
);
}
在 Observable 化的防腐層中,會(huì)存在高階 Observable 與 低階 Observable 兩種設(shè)計(jì),在上文的例子中,F(xiàn)ree Observable 和 Usage Observable 為低階封裝,而 Percent Observable 利用 Free 和 Usage 的 Observable 進(jìn)行了高階封裝,當(dāng)?shù)碗A封裝改動(dòng)時(shí),由于 Observable 本身的特性,高階封裝經(jīng)常是不需要進(jìn)行任何改動(dòng)的,這也是防腐層給我們帶來(lái)的額外好處。
2 調(diào)用方式改變
當(dāng)調(diào)用方式發(fā)生改變時(shí),防腐層同樣可以發(fā)揮作用。/api/v3/memory 直接返回了 free 與 usage 的數(shù)據(jù),接口格式如下。
{
requestId: string;
data: {
free: number;
usage: number;
}
}
防腐層代碼只需要進(jìn)行如下更新,就可以保障組件層代碼無(wú)需修改。
export function getMemoryObservable(): Observable<{ free: number; usage: number }> {
return fromFetch("/api/v3/memory").pipe(
mergeMap((res) => res.json()),
map((data) => data.data)
);
}
export function getMemoryFreeObservable(): Observable<number> {
return getMemoryObservable().pipe(map((data) => data.free));
}
export function getMemoryUsageObservable(): Observable<number> {
return getMemoryObservable().pipe(map((data) => data.usage));
}
export function getMemoryUsagePercent(): Promise<number> {
return lastValue(getMemoryObservable().pipe(
map(({ usage, free }) => +((usage / (usage + free)) * 100).toFixed(2))
));
}
3 多版本共存使用
當(dāng)前端代碼需要在多套環(huán)境下部署時(shí),部分環(huán)境下 v3 的接口可用,而部分環(huán)境下只有 v2 的接口部署,此時(shí)我們依然可以在防腐層屏蔽環(huán)境的差異。
export function getMemoryLegacyObservable(): Observable<{ free: number; usage: number }> {
const legacyUsage = fromFetch("/api/v2/memory/usage").pipe(
mergeMap((res) => res.json())
);
const legacyFree = fromFetch("/api/v2/memory/free").pipe(
mergeMap((res) => res.json())
);
return forkJoin([legacyUsage, legacyFree], (usage, free) => ({
free: free.data.free,
usage: usage.data.usage,
}));
}
export function getMemoryObservable(): Observable<{ free: number; usage: number }> {
const current = fromFetch("/api/v3/memory").pipe(
mergeMap((res) => res.json()),
map((data) => data.data)
);
return race(getMemoryLegacyObservable(), current);
}
export function getMemoryFreeObservable(): Observable<number> {
return getMemoryObservable().pipe(map((data) => data.free));
}
export function getMemoryUsageObservable(): Observable<number> {
return getMemoryObservable().pipe(map((data) => data.usage));
}
export function getMemoryUsagePercent(): Promise<number> {
return lastValue(getMemory().pipe(
map(({ usage, free }) => +((usage / (usage + free)) * 100).toFixed(2))
));
}
通過(guò) race 操作符,當(dāng) v2 與 v3 任何一個(gè)版本的接口可用時(shí),防腐層都可以正常工作,在組件層無(wú)需再關(guān)注接口受環(huán)境的影響。
防腐層不僅僅是多了一層對(duì)接口的封裝與隔離,它還能起到以下作用。
1 概念映射
接口語(yǔ)義與前端需要數(shù)據(jù)的語(yǔ)義有時(shí)并不能完全對(duì)應(yīng),當(dāng)在組件層直接調(diào)用接口時(shí),所有開(kāi)發(fā)者都需要對(duì)接口與界面的語(yǔ)義映射足夠了解。有了防腐層后,防腐層提供的調(diào)用方法包含了數(shù)據(jù)的真實(shí)語(yǔ)義,減少了開(kāi)發(fā)者的二次理解成本。
2 格式適配
在很多情況下,接口返回的數(shù)據(jù)結(jié)構(gòu)與格式與前端需要的數(shù)據(jù)格式并不符合,通過(guò)在防腐層增加數(shù)據(jù)轉(zhuǎn)換邏輯,可以降低接口數(shù)據(jù)對(duì)業(yè)務(wù)代碼的入侵。在以上的案例里,我們封裝了 getMemoryUsagePercent 的數(shù)據(jù)返回,使得組件層可以直接使用百分比數(shù)據(jù),而不需要再次進(jìn)行轉(zhuǎn)換。
3 接口緩存
對(duì)于多種業(yè)務(wù)依賴同一接口的情況,我們可以通過(guò)防腐層增加緩存邏輯,從而有效降低接口的調(diào)用壓力。
與格式適配類似,將緩存邏輯封裝在防腐層可以避免組件層對(duì)數(shù)據(jù)的二次緩存,并可以對(duì)緩存數(shù)據(jù)集中管理,降低代碼的復(fù)雜度,一個(gè)簡(jiǎn)單的緩存示例如下。
class CacheService {
private cache: { [key: string]: any } = {};
getData() {
if (this.cache) {
return of(this.cache);
} else {
return fromFetch("/api/v3/memory").pipe(
mergeMap((res) => res.json()),
map((data) => data.data),
tap((data) => {
this.cache = data;
})
);
}
}
}
4 穩(wěn)定性兜底
當(dāng)接口穩(wěn)定性較差時(shí),通常的做法是在組件層對(duì) response error 的情況進(jìn)行處理,這種兜底邏輯通常比較復(fù)雜,組件層的維護(hù)成本會(huì)很高。我們可以通過(guò)防腐層對(duì)穩(wěn)定性進(jìn)行兜底,當(dāng)接口出錯(cuò)時(shí)可以返回兜底業(yè)務(wù)數(shù)據(jù),由于兜底數(shù)據(jù)統(tǒng)一維護(hù)在防腐層,后續(xù)的測(cè)試與修改也會(huì)更加方便。在上文中的多版本共存的防腐層中,增加以下代碼,此時(shí)即使 v2 和 v3 接口都無(wú)法返回?cái)?shù)據(jù),前端仍然可以保持可用。
return race(getMemoryLegacy(), current).pipe(
+ catchError(() => of({ usage: '-', free: '-' }))
);
5 聯(lián)調(diào)與測(cè)試
接口和前端可能會(huì)存在并行開(kāi)發(fā)的狀態(tài),此時(shí),前端的開(kāi)發(fā)并沒(méi)有真實(shí)的后端接口可用。與傳統(tǒng)的搭建 mock api 的方式相比,在防腐層直接對(duì)數(shù)據(jù)進(jìn)行 mock 是更方便的方案。
export function getMemoryFree(): Observable<number> {
return of(0.8);
}
export function getMemoryUsage(): Observable<number> {
return of(1.2);
}
export function getMemoryUsagePercent(): Observable<number> {
return forkJoin([getMemoryUsage(), getMemoryFree()]).pipe(
map(([usage, free]) => +((usage / (usage + free)) * 100).toFixed(2))
);
}
在防腐層對(duì)數(shù)據(jù)進(jìn)行 mock 也可以用于對(duì)頁(yè)面的測(cè)試,例如 mock 大量數(shù)據(jù)對(duì)頁(yè)面性能影響。
export function getLargeList(): Observable<string[]> {
const options = [];
for (let i = 0; i < 100000; i++) {
const value = `${i.toString(36)}${i}`;
options.push(value);
}
return of(options);
}
在本文中我們介紹了以下內(nèi)容:
請(qǐng)讀者注意,只在特定的場(chǎng)景下引入前端防腐層才是合理的,即前端處于跟隨者或供應(yīng)商/客戶關(guān)系中,且面臨大量接口無(wú)法保障穩(wěn)定和兼容。如果在防腐層可以在后端 Gateway 構(gòu)建,或者接口數(shù)量較少時(shí),引入防腐層帶來(lái)的額外成本會(huì)大于其帶來(lái)的好處。
RxJS 在防腐層構(gòu)建場(chǎng)景下提供的更多的是 Observable 化的能力,如果讀者不需要復(fù)雜的 operators 轉(zhuǎn)換工具,也可以自行構(gòu)建 Observable 構(gòu)建方案,事實(shí)上只需要 100 行的代碼就可以實(shí)現(xiàn) https://stackblitz.com/edit/mini-rxjs。
改造后的前端架構(gòu)將不再直接依賴接口實(shí)現(xiàn),不會(huì)入侵現(xiàn)有前端數(shù)據(jù)層設(shè)計(jì),還可以承擔(dān)概念映射、格式適配、接口緩存、穩(wěn)定性兜底以及協(xié)助聯(lián)調(diào)測(cè)試等工作。文中所有的示例代碼都可以在倉(cāng)庫(kù) https://github.com/vthinkxie/rxjs-acl 獲得。
原文鏈接:https://developer.aliyun.com/article/872430?utm_content=g_1000331001
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。