如何優(yōu)雅處理「快應(yīng)用」數(shù)據(jù)請(qǐng)求

查閱快應(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ōu)雅處理快應(yīng)用數(shù)據(jù)請(qǐng)求

備注: 本文最先發(fā)布于,基于 Ghost 構(gòu)建的最新博客: 靜軒之別苑潦匈。

為保證文中的代碼阱高,是直接拷貝就可以運(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


您可能會(huì)感興趣的文章:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晚缩,隨后出現(xiàn)的幾起案子尾膊,更是在濱河造成了極大的恐慌,老刑警劉巖荞彼,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冈敛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鸣皂,警方通過(guò)查閱死者的電腦和手機(jī)抓谴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寞缝,“玉大人癌压,你說(shuō)我怎么就攤上這事【B剑” “怎么了滩届?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)被啼。 經(jīng)常有香客問(wèn)我帜消,道長(zhǎng),這世上最難降的妖魔是什么浓体? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任泡挺,我火速辦了婚禮,結(jié)果婚禮上命浴,老公的妹妹穿的比我還像新娘娄猫。我一直安慰自己,他們只是感情好生闲,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布媳溺。 她就那樣靜靜地躺著,像睡著了一般跪腹。 火紅的嫁衣襯著肌膚如雪褂删。 梳的紋絲不亂的頭發(fā)上飞醉,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天冲茸,我揣著相機(jī)與錄音屯阀,去河邊找鬼。 笑死轴术,一個(gè)胖子當(dāng)著我的面吹牛难衰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逗栽,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼盖袭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了彼宠?” 一聲冷哼從身側(cè)響起鳄虱,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凭峡,沒想到半個(gè)月后拙已,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摧冀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年倍踪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片索昂。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡建车,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出椒惨,到底是詐尸還是另有隱情缤至,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布框产,位于F島的核電站凄杯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秉宿。R本人自食惡果不足惜戒突,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望描睦。 院中可真熱鬧膊存,春花似錦、人聲如沸忱叭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)韵丑。三九已至爵卒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撵彻,已是汗流浹背钓株。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工实牡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人轴合。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓创坞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親受葛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子题涨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容