js及nodejs由于其單線程特性,對于應(yīng)用中比較耗時(shí)的網(wǎng)絡(luò)請求逮京、磁盤操作均已異步形式完成缘眶。因此嘱根,經(jīng)常看到如下形式
getLocation(res){
if(res.ok){
login(res){
if(res.ok){
setState()
}
}
}
}
getLocation成功后才能執(zhí)行l(wèi)ogin操作巷懈,login成功后才能setState更新數(shù)據(jù)
如果中間還要添加會阻塞當(dāng)前應(yīng)用進(jìn)程的操作该抒,且其數(shù)據(jù)依賴于上一部操作成功返回的結(jié)構(gòu),就需要寫在上一步的成功回調(diào)下顶燕,這樣嵌套層級越來越多凑保,就會陷入所謂的“回調(diào)地獄”。對于此類問題的解決涌攻,有es6的promise和es7的async/await欧引,這里,我們不研究深層次的回調(diào)問題恳谎,只討論當(dāng)遇到這種情況時(shí)维咸,如何將其封裝成一個模塊達(dá)到重復(fù)利用。
以常用的fetch為例
export default function _update(url, data, callback){
let init = {
credentials: 'include',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
mode: 'cors',
body: JSON.stringify(data)
}
fetch(url, init)
.then(res => res.json())
.then(res => {
// fetch請求得到相應(yīng)惠爽,根據(jù)回傳的res執(zhí)行下一步操作
callback(res)
})
}
_update為封裝的一個通用fetch模塊,接受請求url瞬哼,請求時(shí)發(fā)送給服務(wù)端的數(shù)據(jù)婚肆,以及請求成功時(shí)需要執(zhí)行的回調(diào)函數(shù)三個參數(shù)。callback的傳遞保證fetch在服務(wù)端有數(shù)據(jù)返回后調(diào)用坐慰,因此较性,可以像如下形式使用這個模塊用僧。
import update from 'update.js'
update('https://xxx', {
name: 'xm',
age: 12
}, res => {
console.log(res)
})
傳遞給update三個參數(shù),對應(yīng)于模塊中的形參赞咙。
調(diào)用函數(shù)中第三個函數(shù)參數(shù)
res => {
console.log(res)
}
對應(yīng)于模塊中的callback(res)责循,相當(dāng)于
function callback(res){
console.log(res)
}
如果在update前先要獲取到當(dāng)前位置
function getLocation(callback){
......
if(res){
callback(url)
}
}
如果獲取位置成功,將位置信息res傳遞給update函數(shù)攀操,update在fetch請求得到相應(yīng)后刷新數(shù)據(jù)院仿,那么將getLocation改造成如下即可
function getLocation(callback){
......
if(res){
callback('https://xxx', {
location: res
}, res => {
cosole.log(res)
})
}
}
兩個res,一個是獲取到位置回傳的res速和,另一個是fetch請求相應(yīng)回傳的res
調(diào)用只需要一行代碼
getLocation(update)
可以將update的三個參數(shù)傳遞給getLocation歹垫,達(dá)到更大的復(fù)用性。但這樣一來颠放,代碼脈絡(luò)不夠清晰排惨,顯得有些累贅了。
建議只有一層回調(diào)時(shí)使用這種封裝方法碰凶,如果對方法有更好的設(shè)計(jì)暮芭,多層回調(diào)時(shí)也不妨一試。