怎么在JavaScript中實(shí)現(xiàn)一個(gè)適配器功能

這篇文章主要介紹了怎么在JavaScript中實(shí)現(xiàn)一個(gè)適配器功能,此處通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考價(jià)值,需要的朋友可以參考下:

創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作與策劃設(shè)計(jì),邕寧網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:邕寧等地區(qū)。邕寧做網(wǎng)站價(jià)格咨詢:028-86922220

JavaScript是什么

JavaScript是一種直譯式的腳本語(yǔ)言,其解釋器被稱為JavaScript引擎,是瀏覽器的一部分,JavaScript是被廣泛用于客戶端的腳本語(yǔ)言,最早是在HTML網(wǎng)頁(yè)上使用,用來(lái)給HTML網(wǎng)頁(yè)增加動(dòng)態(tài)功能。

接入多個(gè)第三方SDK

舉個(gè)日常開(kāi)發(fā)中的例子,我們?cè)谧鲆粋€(gè)微信公眾號(hào)開(kāi)發(fā),里邊用到了微信的支付模塊,經(jīng)過(guò)長(zhǎng)時(shí)間的聯(lián)調(diào),終于跑通了整個(gè)流程,正當(dāng)你準(zhǔn)備開(kāi)心的打包上線代碼的時(shí)候,得到了一個(gè)新需求:
我們需要接入支付寶公眾號(hào)的SDK,也要有支付的流程

為了復(fù)用代碼,我們可能會(huì)在腳本中寫(xiě)下這樣的邏輯:

if (platform === 'wechat') {
 wx.pay(config)
} else if (platform === 'alipay') {
 alipay.pay(config)
}
// 做一些后續(xù)的邏輯處理

但是一般來(lái)說(shuō),各廠的SDK所提供的接口調(diào)用方式都會(huì)多多少少有些區(qū)別,雖說(shuō)有些時(shí)候文檔可能用的是同一份,致敬友商。

所以針對(duì)上述的代碼可能是這樣的:

// 并不是真實(shí)的參數(shù)配置,僅僅舉例使用
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
 })
}

就目前來(lái)說(shuō),代碼接口還算是清晰,只要我們寫(xiě)好注釋,這也不是一個(gè)太糟糕的代碼。

但是生活總是充滿了意外,我們又接到了需求需要添加QQ的SDK、美團(tuán)的SDK、小米的SDK,或者某些銀行的SDK。

此時(shí)你的代碼可能是這樣的:

switch (platform) {
 case 'wechat':
 // 微信的處理邏輯
 break
 case 'QQ':
 // QQ的處理邏輯
 break
 case 'alipay':
 // 支付寶的處理邏輯
 break
 case 'meituan':
 // 美團(tuán)的處理邏輯
 break
 case 'xiaomi':
 // 小米的處理邏輯
 break
}

這已經(jīng)不是一些注釋能夠彌補(bǔ)的問(wèn)題了,這樣的代碼會(huì)變得越來(lái)越難維護(hù),各種SDK千奇百怪的調(diào)用方式,如果其他人也要做類似的需求,還需要重新寫(xiě)一遍這樣的代碼,那肯定是很浪費(fèi)資源的一件事兒。

所以為了保證我們業(yè)務(wù)邏輯的清晰,同時(shí)也為了避免后人重復(fù)的踩這個(gè)坑,我們會(huì)將它進(jìn)行拆分出來(lái)作為一個(gè)公共的函數(shù)來(lái)存在:

找到其中某一個(gè)SDK的調(diào)用方式或者一個(gè)我們約定好的規(guī)則作為基準(zhǔn)。

我們來(lái)告訴調(diào)用方,你要怎么怎么做,你能怎樣獲取返回?cái)?shù)據(jù),然后我們?cè)诤瘮?shù)內(nèi)部進(jìn)行這些各種骯臟的判斷:

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
 }
 })
}

這樣無(wú)論我們?cè)谑裁喘h(huán)境下,只要我們的適配器支持,就可以按照我們約定好的通用規(guī)則進(jìn)行調(diào)用,而具體執(zhí)行的是什么SDK,則是適配器需要關(guān)心的事情:

// run anywhere
await pay({
 price: 10,
 goodsId: 1
})

對(duì)于SDK提供方,僅僅需要知道自己所需要的一些參數(shù),然后按照自己的方式進(jìn)行數(shù)據(jù)返回。

對(duì)于SDK調(diào)用方,僅僅需要我們約定好的通用的參數(shù),以及按照約定的方式進(jìn)行監(jiān)聽(tīng)回調(diào)處理。

整合多個(gè)第三方SDK的任務(wù)就交由適配器來(lái)做,然后我們將適配器的代碼壓縮,混淆,放在一個(gè)看不見(jiàn)的角落里去,這樣的代碼邏輯就會(huì)變得很清晰了 :)。

適配器大致就是這樣的作用,有一點(diǎn)一定要明確,適配器不是銀彈,__那些繁瑣的代碼始終是存在的,只不過(guò)你在寫(xiě)業(yè)務(wù)的時(shí)候看不到它罷了__,眼不見(jiàn)心不煩。

一些其他的例子

個(gè)人覺(jué)得,jQuery中就有很多適配器的例子,包括最基礎(chǔ)的$('selector').on,這個(gè)不就是一個(gè)很明顯的適配器模式么?

一步步的進(jìn)行降級(jí),并且抹平了一些瀏覽器之間的差異,讓我們可以通過(guò)簡(jiǎn)單的on來(lái)進(jìn)行在主流瀏覽器中進(jìn)行事件監(jiān)聽(tīng):

// 一個(gè)簡(jiǎn)單的偽代碼示例
function on (target, event, callback) {
 if (target.addEventListener) {
 // 標(biāo)準(zhǔn)的監(jiān)聽(tīng)事件方式
 target.addEventListener(event, callback)
 } else if (target.attachEvent) {
 // IE低版本的監(jiān)聽(tīng)方式
 target.attachEvent(event, callback)
 } else {
 // 一些低版本的瀏覽器監(jiān)聽(tīng)事件方式
 target[`on${event}`] = callback
 }
}

或者在Node中的這樣的例子更是常見(jiàn),因?yàn)樵缒晔菦](méi)有Promise的,所以大多數(shù)的異步由callback來(lái)完成,且有一個(gè)約定好的規(guī)則,Error-first callback:

const fs = require('fs')
fs.readFile('test.txt', (err, data) => {
 if (err) // 處理異常
 // 處理正確結(jié)果
})

而我們的新功能都采用了async/await的方式來(lái)進(jìn)行,當(dāng)我們需要復(fù)用一些老項(xiàng)目中的功能時(shí),直接去修改老項(xiàng)目的代碼肯定是不可行的。
這樣的兼容處理需要調(diào)用方來(lái)做,所以為了讓邏輯代碼看起來(lái)不是太混亂,我們可能會(huì)將這樣的回調(diào)轉(zhuǎn)換為Promise的版本方便我們進(jìn)行調(diào)用:

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')

因?yàn)榍斑呉蔡岬搅?,這種Error-first callback是一個(gè)約定好的形式,所以我們可以很輕松的實(shí)現(xiàn)一個(gè)通用的適配器:

function promisify(func) {
 return (...args) => new Promise((resolve, reject) => {
 func(...args, (err, data) => {
  if (err) reject(err)
  resolve(data)
 })
 })
}

然后在使用前進(jìn)行對(duì)應(yīng)的轉(zhuǎn)換就可以用我們預(yù)期的方式來(lái)執(zhí)行代碼:

const fs = require('fs')
const readFile = promisify(fs.readFile)
await readFile('test.txt')

到此這篇關(guān)于怎么在JavaScript中實(shí)現(xiàn)一個(gè)適配器功能的文章就介紹到這了,更多相關(guān)怎么在JavaScript中實(shí)現(xiàn)一個(gè)適配器功能的內(nèi)容請(qǐng)搜索創(chuàng)新互聯(lián)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持創(chuàng)新互聯(lián)!

網(wǎng)頁(yè)標(biāo)題:怎么在JavaScript中實(shí)現(xiàn)一個(gè)適配器功能
URL標(biāo)題:http://muchs.cn/article30/pipeso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、網(wǎng)站排名、網(wǎng)站建設(shè)、網(wǎng)站維護(hù)企業(yè)建站、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名