查閱快應(yīng)用開發(fā)文檔,可以知道官方提供了數(shù)據(jù)請(qǐng)求接口鼎俘;對(duì)于如何使用哲身,文檔中也給出了簡(jiǎn)單的說(shuō)明和代碼示例,但很顯然贸伐,這在實(shí)際項(xiàng)目中勘天,不夠科學(xué)優(yōu)雅、且更不高效捉邢,所以需要對(duì)其進(jìn)行再封裝脯丝,使得可以大幅提升開發(fā)效率,同時(shí)也令整個(gè)代碼優(yōu)雅伏伐,以便于維護(hù)巾钉。所以在此篇文章的存在,旨在于討論下如何優(yōu)雅處理「快應(yīng)用」數(shù)據(jù)請(qǐng)求秘案。
為保證文中的代碼阱高,是直接拷貝就可以運(yùn)行的,特有引用網(wǎng)絡(luò)開源接口茬缩;需要備注說(shuō)明的是赤惊,在快應(yīng)用使用接口,需要在
manifest.json
中凰锡,對(duì)所使用的接口進(jìn)行聲明未舟;使用數(shù)據(jù)請(qǐng)求,就需要注入下面的聲明:
{ "name": "system.fetch" }
默認(rèn)的低效率寫法
import $fetch from '@system.fetch'
$fetch.fetch({
url: 'https://api.apiopen.top/singlePoetry',
responseType: 'text',
success: function (response) {
const result = response.data
console.log(`success response, code: ${result.code}, data: ${result.data}`)
},
fail: function (data, code) {
console.log(`fetch handling fail, code = ${code}`)
},
complete: funtion (data, code) {
console.log(`fetch handling complete, code = ${code}`)
}
})
以上就是官方文檔提供的上古 jQuery
時(shí)代的寫法掂为,冗長(zhǎng)的代碼裕膀,古老的回調(diào)式操作,以及對(duì)請(qǐng)求沒有做任何必要的處理勇哗,如果這在項(xiàng)目中使用昼扛,對(duì)代碼復(fù)用度無(wú)疑是零,從長(zhǎng)期維護(hù)角度看欲诺,這樣的代碼就是導(dǎo)致痛苦的根源抄谐。雖然渺鹦,示例代碼這樣寫道,也無(wú)可厚非蛹含;但先入為主的模范作用毅厚,將對(duì)于諸多經(jīng)驗(yàn)不夠充足的開發(fā)者,起到錯(cuò)誤的誤導(dǎo)性引領(lǐng)浦箱。
改進(jìn)后的用法
import $fetch from '@system.fetch'
$fetch.fetch({
url: 'https://api.apiopen.top/singlePoetry',
method: 'GET'
}).then(response => {
const result = response.data
console.log(`success response, code: ${result.code}, data: ${result.data}`)
}).catch(error => {
console.log(`Something Error: ${error}`)
})
其實(shí)吸耿,快應(yīng)用對(duì)部分接口方法調(diào)用,返回了 Promise 優(yōu)化憎茂,其中就包括數(shù)據(jù)請(qǐng)求接口珍语;所以,使用如上這種方式竖幔,至少代碼顯得不那么冗長(zhǎng)而古老板乙。但,數(shù)據(jù)請(qǐng)求相關(guān)代碼拳氢,卻依然沒有得到復(fù)用募逞,這就需要對(duì)其進(jìn)行封裝處理。
優(yōu)化處理數(shù)據(jù)請(qǐng)求
如果每次調(diào)用接口馋评,都需要 import放接,外加指定 url,method 等參數(shù)留特,這無(wú)異是變相的浪費(fèi)生命纠脾;大道至簡(jiǎn),優(yōu)秀的開發(fā)流程蜕青,一定是便于編寫和維護(hù)苟蹈!所以有必要將其統(tǒng)一封裝,如下面所封裝的代碼(可放置在 helpera/ajax.js
路徑下):
function requestHandle(params) {
return new Promise((resolve, reject) => {
$fetch.fetch({
url: params.url,
method: params.method,
data: params.data
}).then(response => {
const result = response.data
const content = JSON.parse(result.data)
/* @desc: 可跟具體不同業(yè)務(wù)接口數(shù)據(jù)右核,返回你所需要的部分慧脱,使得使用盡可能便捷 */
content.code === 200 ? resolve(content.result) : resolve(content.message)
}).catch((error, code) => {
console.log(`?? request fail, code = ${code}`)
reject(error)
})
})
}
/* 此處只是處于示例代碼的可運(yùn)行性,實(shí)際項(xiàng)目中贺喝,此方法最好予以封裝 & 提取 */
function queryString(url, query) {
let str = []
for (let key in query) {
if (typeof query[key] === 'object') {
query[key] = JSON.stringify(query[key])
}
str.push(key + '=' + query[key])
}
let paramStr = str.join('&')
return paramStr ? `${url}?${paramStr}` : url
}
export default {
post: function(url, params) {
return requestHandle({
method: 'post',
url: url,
data: params
})
},
get: function(url, params) {
return requestHandle({
method: 'get',
url: queryString(url, params)
})
}
}
這 $fetch.fetch 返回本就是一個(gè) Promise
菱鸥,這里為何額外要包裹的一層處理呢?這樣做的好處不僅在于使其依舊可以鏈?zhǔn)秸{(diào)用躏鱼,同時(shí)對(duì)返回?cái)?shù)據(jù)統(tǒng)一處理氮采,精簡(jiǎn)返回內(nèi)容,使得在獲取到最終結(jié)果處染苛,可以盡可能簡(jiǎn)單扳抽,更加有利于后期做維護(hù),調(diào)用方式就可以成為如下這樣(涉及某類模塊,可統(tǒng)一在相應(yīng)模塊文件下贸呢,如:helper/apis/poetry.js
):
import $ajax from './../ajax'
const baseUrl = 'https://api.apiopen.top/'
export default {
getSinglePoetry(data) {
return $ajax.get(`${baseUrl}singlePoetry`, data)
},
getOtherApi(data) {
// other api ....
}
}
另外镰烧,開發(fā)者將接口,按照功能模塊規(guī)劃楞陷,分門別類以存放至統(tǒng)一文件夾下怔鳖,如 helper/apis;如此清晰明了固蛾,方便調(diào)用结执,且對(duì)于多人協(xié)作開發(fā),又不相互響應(yīng)艾凯,減少不必要的沖突献幔。類似善用配置,以表驅(qū)動(dòng)法的編程手法趾诗,應(yīng)該活學(xué)活用蜡感,貫穿始終。這些理念恃泪,早在更優(yōu)雅的處理-Http-請(qǐng)求 | 開箱即用的 Vue Webpack 腳手架模版中就有闡述郑兴。
至此,就對(duì)接口進(jìn)行了完美封裝處理贝乎;在業(yè)務(wù)層便捷調(diào)用情连,也是需要優(yōu)化;在快應(yīng)用览效,最為高效的辦法却舀,就是將上面封裝暴露給 global
,如此就可以:
import { $apis } from './helper'
const hook2global = global.__proto__ || global
hook2global.$apis = $apis
// 在任何其他頁(yè)面锤灿、組件挽拔、js 文件,接可以像如下調(diào)用
const params = {}
$apis.poetry.getSinglePoetry(params).then(result => {
// 處理正常邏輯
}).catch(error => {
// 處理請(qǐng)求異常邏輯
})
更近一步體驗(yàn)優(yōu)化
在業(yè)務(wù)邏輯中衡招,發(fā)起數(shù)據(jù)請(qǐng)求時(shí)候,都需要添加 Loading每强,提示用戶請(qǐng)求正在進(jìn)行中始腾,以免響應(yīng)緩慢給用戶帶來(lái)不必要的疑惑;而空执,在請(qǐng)求成功或失敗情形下浪箭,都需要對(duì) Loading 進(jìn)行消除,如此一來(lái)就會(huì)有下面的邏輯:
$apis.poetry.getSinglePoetry(params).then(result => {
this.isLoading = false
// 處理正常邏輯
}).catch(error => {
// 處理請(qǐng)求異常邏輯
this.isLoading = false
})
很明顯辨绊,像類似不管請(qǐng)求成功或失敗奶栖,都需要執(zhí)行的業(yè)務(wù)邏輯是存在的,如果分別在對(duì)應(yīng)鏈?zhǔn)胶笞鎏幚恚労蝺?yōu)雅呢宣鄙?在 ES2018
有引入 finally
標(biāo)準(zhǔn)袍镀,跟快應(yīng)用中請(qǐng)求后 complete
回調(diào)是一樣的作用:不管最后狀態(tài)如何,都會(huì)執(zhí)行的操作冻晤。所以上面的調(diào)用苇羡,就可以優(yōu)化成如下代碼:
$apis.poetry.getSinglePoetry(params).then(result => {
// 處理正常邏輯
}).catch(error => {
// 處理請(qǐng)求異常邏輯
}).finally(() => {
this.isLoading = false
})
當(dāng)按照預(yù)期這樣寫的時(shí)候,你會(huì)發(fā)現(xiàn) finally 鏈?zhǔn)讲⑽吹玫秸{(diào)用鼻弧。查閱一番设江,興許你也會(huì)得到一個(gè)答案,快應(yīng)用規(guī)范沒有 finally攘轩,如此一來(lái)叉存,就不得不打補(bǔ)丁 (polyfill) 來(lái)予以解決了,可以有的途徑不少度帮,下面介紹一種簡(jiǎn)單無(wú)依賴的法子歼捏,注入以下代碼即可;那么上面關(guān)于 ajax.js
的封裝則可以優(yōu)化成如下代碼:
Promise.prototype.finally = function (callback) {
const P = this.constructor
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
)
}
function requestHandle(params) {
return new Promise((resolve, reject) => {
$fetch.fetch({
url: params.url,
method: params.method,
data: params.data
}).then(response => {
const result = response.data
const content = JSON.parse(result.data)
/* @desc: 可跟具體不同業(yè)務(wù)接口數(shù)據(jù)够傍,返回你所需要的部分甫菠,使得使用盡可能便捷 */
content.code === 200 ? resolve(content.result) : resolve(content.message)
}).catch((error, code) => {
console.log(`?? request fail, code = ${code}`)
reject(error)
}).finally(() => {
console.log(`?? request @${params.url} has been completed.`)
resolve()
})
})
}
需要補(bǔ)充說(shuō)明的是,
finally
方法指定的回調(diào)函數(shù)冕屯,用于指定不管 Promise 對(duì)象最后狀態(tài)如何寂诱,都會(huì)執(zhí)行的操作;它是與狀態(tài)無(wú)關(guān)的安聘,不依賴于 Promise 的執(zhí)行結(jié)果痰洒,所以此處 polyfill 返回跟標(biāo)準(zhǔn)一致,回調(diào)函數(shù)不接受任何參數(shù)浴韭。
關(guān)于快應(yīng)用數(shù)據(jù)請(qǐng)求的整體代碼優(yōu)化設(shè)計(jì)丘喻,具體可參見 Github 項(xiàng)目:quickapp-boilerplate-template: ??致力于構(gòu)建更為優(yōu)雅的「快應(yīng)用」開發(fā)腳手架模板。
至此念颈,對(duì)處理「快應(yīng)用」數(shù)據(jù)請(qǐng)求泉粉,相比開發(fā)文檔中所寫到的示例,是不是優(yōu)雅很多呢榴芳?如果你的項(xiàng)目中嗡靡,涉及數(shù)據(jù)請(qǐng)求有超過(guò) 3 個(gè)的可能,那么你就應(yīng)該做像著樣窟感。當(dāng)然讨彼,這不僅僅限于此接口,其他如數(shù)據(jù)存儲(chǔ)(storage)柿祈,上傳下載(request)哈误,你都應(yīng)該予以封裝哩至。這也不僅僅限于快應(yīng)用,其他如開發(fā) Vue
蜜自、React
等項(xiàng)目菩貌,亦是同理。
@2019-01-17 于深圳.福田 Last Modify:2018-01-19