這篇文章帶給大家的內容是關於適配器在JavaScript中的應用(附範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
適配器設計模式在JavaScript中非常有用,在處理跨瀏覽器相容問題、整合多個第三方SDK的調用,都可以看到它的身影。
其實在日常開發中,很多時候會不經意地寫出符合某種設計模式的程式碼,畢竟設計模式就是老前輩們總結提煉出來的一些能夠幫助提升開發效率的一些模版,源於日常的開發中。
而適配器其實在JavaScript中應該是比較常見的一種了。
在維基百科中,關於適配器模式的定義為:
在軟體工程中,適配器模式是一種軟體設計模式,允許從另一個介面使用現有類別的介面。它通常用於使現有的類別與其他類別一起工作,而無需修改其原始程式碼。
生活中的例子
在生活中最常見的就是電源插頭的適配器了,世界各國的插座標準各不相同,如果需要根據各國的標準購買對應的電源插頭那未免太過於浪費錢財,如果說自己帶著插座,把人家牆敲碎,重新接線,也肯定是不切實際的。
所以會有插頭的轉接器,用來將某種插頭轉換成另一種插頭,在插座和你的電源之間做中轉的這個東西,就是轉接器。
在程式碼中的體現
#而轉向程式設計中,我個人是這樣理解的:
將那些你不願意看見的髒程式碼藏起來,你就可以說這是一個適配器接入多個第三方SDK
舉個日常開發中的例子,我們在做一個微信公眾號開發,裡邊用到了微信的支付模組,經過長時間的聯調,終於跑通了整個流程,正當你準備開心的打包上線代碼的時候,得到了一個新需求:
我們需要接入支付寶公眾號的SDK,也要有支付的流程
為了復用程式碼,我們可能會在腳本中寫下這樣的邏輯:
if (platform === 'wechat') { wx.pay(config) } else if (platform === 'alipay') { alipay.pay(config) } // 做一些后续的逻辑处理
但是一般來說,各廠的SDK所提供的介面呼叫方式都會多多少少有些差別,雖說有些時候文檔可能用的是同一份,致敬友商。
所以針對上述的程式碼可能是這樣的:
// 并不是真实的参数配置,仅仅举例使用 const config = { price: 10, goodsId: 1 } // 还有可能返回值的处理方式也不相同 if (platform === 'wechat') { config.appId = 'XXX' config.secretKey = 'XXX' wx.pay(config).then((err, data) => { if (err) // error // success }) } else if (platform === 'alipay') { config.token = 'XXX' alipay.pay(config, data => { // success }, err => { // error }) }
就目前來說,程式碼介面還算是清晰,只要我們寫好註釋,這也不是一個太糟糕的代碼。
但人生總是充滿了意外,我們又接到了需求需要增加QQ的SDK、美團的SDK、小米的SDK,或是某些銀行的SDK。
此時你的程式碼可能是這樣的:
switch (platform) { case 'wechat': // 微信的处理逻辑 break case 'QQ': // QQ的处理逻辑 break case 'alipay': // 支付宝的处理逻辑 break case 'meituan': // 美团的处理逻辑 break case 'xiaomi': // 小米的处理逻辑 break }
這已經不是一些註解能夠彌補的問題了,這樣的程式碼會變得越來越難維護,各種SDK千奇百怪的呼叫方式,如果其他人也要做類似的需求,還需要重新寫一遍這樣的程式碼,那肯定是很浪費資源的一件事。
所以為了確保我們業務邏輯的清晰,同時也為了避免後人重複的踩這個坑,我們會將它進行拆分出來作為一個公共的函數來存在:
找到其中某一個SDK的呼叫方式或一個我們約定好的規則作為基準。
我們來告訴呼叫方,你要怎麼做,你能怎樣取得回傳數據,然後我們在函數內部進行這些各種骯髒的判斷:
function pay ({ price, goodsId }) { return new Promise((resolve, reject) => { const config = {} switch (platform) { case 'wechat': // 微信的处理逻辑 config.price = price config.goodsId = goodsId config.appId = 'XXX' config.secretKey = 'XXX' wx.pay(config).then((err, data) => { if (err) return reject(err) resolve(data) }) break case 'QQ': // QQ的处理逻辑 config.price = price * 100 config.gid = goodsId config.appId = 'XXX' config.secretKey = 'XXX' config.success = resolve config.error = reject qq.pay(config) break case 'alipay': // 支付宝的处理逻辑 config.payment = price config.id = goodsId config.token = 'XXX' alipay.pay(config, resolve, reject) break } }) }
這樣無論我們在什麼環境下,只要我們的適配器支持,就可以按照我們約定好的通用規則進行調用,而具體執行的是什麼SDK,則是適配器需要關心的事情:
// run anywhere await pay({ price: 10, goodsId: 1 })
對於SDK提供方,僅僅需要知道自己所需要的一些參數,然後按照自己的方式進行資料回傳。
對於SDK呼叫房,只需要我們約定好的通用的參數,以及依照約定的方式進行監聽回調處理。
整合多個第三方SDK的任務就交由適配器來做,然後我們將適配器的程式碼壓縮,混淆,放在一個看不見的角落裡去,這樣的程式碼邏輯就會變得很清晰了:)。
適配器大致就是這樣的作用,有一點一定要明確,適配器不是銀彈,__那些繁瑣的代碼始終是存在的,只不過你在寫業務的時候看不到它罷了__,眼不見為淨。
一些其他的例子
個人覺得,jQuery
中就有很多適配器的例子,包括最基礎的$('selector').on
,這個不就是一個很明顯的轉接器模式麼?
一步步的進行降級,並且抹平了一些瀏覽器之間的差異,讓我們可以透過簡單的on
來進行在主流瀏覽器中進行事件監聽:
// 一个简单的伪代码示例 function on (target, event, callback) { if (target.addEventListener) { // 标准的监听事件方式 target.addEventListener(event, callback) } else if (target.attachEvent) { // IE低版本的监听方式 target.attachEvent(event, callback) } else { // 一些低版本的浏览器监听事件方式 target[`on${event}`] = callback } }
或者在Node中的这样的例子更是常见,因为早年是没有Promise
的,所以大多数的异步由callback
来完成,且有一个约定好的规则,Error-first callback
:
const fs = require('fs') fs.readFile('test.txt', (err, data) => { if (err) // 处理异常 // 处理正确结果 })
而我们的新功能都采用了async/await
的方式来进行,当我们需要复用一些老项目中的功能时,直接去修改老项目的代码肯定是不可行的。
这样的兼容处理需要调用方来做,所以为了让逻辑代码看起来不是太混乱,我们可能会将这样的回调转换为Promise
的版本方便我们进行调用:
const fs = require('fs') function readFile (fileName) { return new Promise((resolve, reject) => { fs.readFile(fileName, (err, data) => { if (err) reject(err) resolve(data) }) }) } await readFile('test.txt')
因为前边也提到了,这种Error-first callback
是一个约定好的形式,所以我们可以很轻松的实现一个通用的适配器:
function promisify(func) { return (...args) => new Promise((resolve, reject) => { func(...args, (err, data) => { if (err) reject(err) resolve(data) }) }) }
然后在使用前进行对应的转换就可以用我们预期的方式来执行代码:
const fs = require('fs') const readFile = promisify(fs.readFile) await readFile('test.txt')在Node8中,官方已经实现了类似这样的工具函数:util.promisify
小结
个人观点:所有的设计模式都不是凭空想象出来的,肯定是在开发的过程中,总结提炼出的一些高效的方法,这也就意味着,可能你并不需要在刚开始的时候就去生啃这些各种命名高大上的设计模式。
因为书中所说的场景可能并不全面,也可能针对某些语言,会存在更好的解决办法,所以生搬硬套可能并不会写出有灵魂的代码 :)
以上是適配器在JavaScript中的應用(附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver Mac版
視覺化網頁開發工具

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),