對于小程序而言,網(wǎng)絡(luò)請求封裝的要比Android強大多了,這一點值得贊揚聚谁。官方示例:
wx.request({
url: 'test.php', //僅為示例,并非真實的接口地址
data: {
x: '' ,
y: ''
},
header: {
'content-type': 'application/json' // 默認值
},
success: function(res) {
console.log(res.data)
}
})
but...but...這調(diào)用起來貌似很簡單爆价,但是垦巴,似乎有點不對勁?哪兒不對勁呢——每次調(diào)用的代碼太多了铭段。而且骤宣,對于網(wǎng)絡(luò)請求的日志文件不好管理。這離我們最理想的方式還是有點差距的序愚。
那么憔披,我們最理想的方式是希望是怎么樣的呢?
1爸吮、代碼簡潔芬膝,一行代碼去搞定。
2形娇、對于常用的字段統(tǒng)一封裝管理锰霜。如 token、版本號version等
3桐早、自定義異常處理癣缅。如未登錄時,不用每寫一個接口都去判斷是否登錄哄酝、注冊等
api.request1(data, function (result) { //數(shù)據(jù)請求成功友存,
},
function(error){//失敗
})
那么陶衅,基于上面的問題屡立。我來一步步進行剖析。
一搀军、網(wǎng)絡(luò)請求的場景分析
1膨俐、支持token傳入的網(wǎng)絡(luò)請求。
這種情況比較少見的罩句。我現(xiàn)在的項目中就遇到了焚刺。大概意思是管理員可以操作旗下的其他的虛擬用戶。管理員登錄后生成一個token的止,每生成一個成員時檩坚,會生成一個虛擬的virtualToekn,以后每次管理員操作這個成員時,都需要用這個virtualToken匾委,但是管理員獲取自己的信息時拖叙,還是需要用自己的token。這個時候就要支持自定義的token傳入了赂乐。
2薯鳍、網(wǎng)絡(luò)請求的劫持。
這種場景主要有兩種情況:
1挨措、如果網(wǎng)絡(luò)失敗
2挖滤、沒有token時,這種場景主要出現(xiàn)在登錄后置中浅役。如商城類app查看購物車等
解決方法:直接返回失敗斩松,在發(fā)起網(wǎng)絡(luò)請求前結(jié)束本次網(wǎng)絡(luò)請求操作,減少預(yù)知的錯誤網(wǎng)絡(luò)訪問
3觉既、支持自定義loading窗的彈出和隱藏控制
1惧盹、loading窗的彈出:這種場景比較多,如下拉刷新列表時瞪讼,是不需要loading窗出現(xiàn)的钧椰。但是獲取用戶信息是需要loading出現(xiàn)的
2、loading窗的隱藏:這種場景是如果調(diào)用一個接口成功后符欠,然后要連續(xù)調(diào)用第二個接口嫡霞。這樣在第一次接口成功后,不應(yīng)該讓loading窗消失希柿,而是最后一次接口結(jié)束后才隱藏诊沪。
4、對網(wǎng)絡(luò)不同的錯誤狡汉,進行處理
二娄徊、代碼分析
/**
* 自定義token 請求
*
* isShowLoading :true 彈出loading窗
* isEndLoading: true 最后需要隱藏loading窗闽颇。若是false盾戴,則不隱藏
* token: 可以自定義token。用戶虛擬賬號使用車輛
*/
export function requestApi(requestData, isShowLoading = true,isEndLoading = true, token = null,onSuccess, onFail) {
let app = getApp().globalData;
// 1兵多、檢查是否已經(jīng)登錄尖啡,在未登錄的時候,可以提前緩存一個臨時token欺騙本次檢查剩膘。等登錄完成后衅斩,再更新token值
if (!util.hasLogin()) {
return;
}
// 2、檢查網(wǎng)絡(luò)狀態(tài)
if (!util.checkNetworkConnected()) { //沒有網(wǎng)絡(luò)
onFail("網(wǎng)絡(luò)請求失敗怠褐,稍后再試")
return;
}
if (!requestData) {
onFail("數(shù)據(jù)異常畏梆,請稍后再試")
return;
}
let cacheToken = util.takeToken()
let newToken = token == null ? cacheToken : token
console.log("newToken===========>", newToken)
requestData.token = newToken
requestData.version = app.version
console.log("==================================================開始請求網(wǎng)絡(luò)數(shù)據(jù)start========================================")
console.log(requestData)
console.log("==================================================開始請求網(wǎng)絡(luò)數(shù)據(jù)end===========================================")
var baseUrl = app.debug ? app.debugUrl : app.releaseUrl
console.log("===baseUrl===>" + baseUrl)
if (isShowLoading){
util.showLoading("加載中")
}
const requestTask = wx.request({
url: baseUrl,
data: requestData,
header: {
'content-type': 'application/json'
},
method: 'POST',
dataType: 'json',
success: function(res) {
console.log("==================================================返回請求結(jié)果start========================================")
console.log(res.data)
console.log("==================================================返回請求結(jié)果end===========================================")
if (res.data.code == 0) { //成功
// console.log("onSuccess===========>", onSuccess);
onSuccess(res.data)
} else if (res.data.code == 1021) { //未繳納押金
wx.navigateTo({
url: '/pages/recharge/recharge',
})
return false;
} else if (res.data.code == 1006) { //余額不足
wx.navigateTo({
url: '/pages/deposited/deposited',
})
return false;
} else if (res.data.code == 1019) { //未實名
wx.navigateTo({
url: '/pages/certify/certify',
})
return false;
} else if (res.data.code == 1001) { //token過期
wx.reLaunch({
url: '/pages/login/login'
});
return false;
} else { //失敗
let error = res.data == null || typeof (res.data) == "undefined" ? "網(wǎng)絡(luò)請求失敗,請稍后再試" : res.data.desc
onFail(error)
console.log("error===========>", error);
}
},
fail: function(res) {
console.log("onFail===========>", res);
onFail("網(wǎng)絡(luò)請求失敗,稍后再試")
},
complete: function(res) {
console.log("complete===========>", isEndLoading);
if (isEndLoading){
wx.hideLoading()
}
}
})
};
三奠涌、網(wǎng)絡(luò)環(huán)境統(tǒng)一切換宪巨。
在app.json中統(tǒng)一配置
// 全局的數(shù)據(jù),可以提供給所有的page頁面使用
globalData: {
token: "",
version: "version版本號",
releaseUrl: "正式版url",
debugUrl: "測試版url",
debug: true //true debug環(huán)境溜畅,false正式環(huán)境
},
這樣捏卓,以后切換網(wǎng)絡(luò)環(huán)境只需要修改debug值即可。
四慈格、二次封裝
/**
* 自定義loading 框請求
*
* isShowLoading :true 彈出loading窗
* isEndLoading: true 最后需要隱藏loading窗怠晴。若是false,則不隱藏
*/
export function request(requestData, isShowLoading = true, isEndLoading = true, onSuccess, onFail){
this.requestApi(requestData, isShowLoading, isEndLoading, null, function (result) {
onSuccess(result)
}, function (error) {
onFail(error)
})
}
/**
* 帶有l(wèi)oading 框的 不能自定義的請求
*
*/
export function request1(requestData, onSuccess, onFail) {
// console.log("onSuccess========request1===>", success, fail);
requestApi(requestData, true, true, null, function (result) {
onSuccess(result)
}, function (error) {
onFail(error)
})
}
/**
* 自定義token 請求
*
* isShowLoading :true 彈出loading窗
* isEndLoading: true 最后需要隱藏loading窗浴捆。若是false蒜田,則不隱藏
* token: 可以自定義token。用戶虛擬賬號使用車輛
*/
export function request2(requestData, isShowLoading = true, isEndLoading = true, token = null, onSuccess, onFail) {
requestApi(requestData, isShowLoading, isEndLoading, token, function (result) {
onSuccess(result)
}, function (error) {
onFail(error)
})
}
/**
* 自定義loading 框請求
*
* isShowLoading :true 彈出loading窗
* isEndLoading: true 最后需要隱藏loading窗选泻。若是false物邑,則不隱藏
*/
export function request3(requestData, isShowLoading = true, isEndLoading = true, token, onSuccess, onFail) {
requestApi(requestData, isShowLoading, isEndLoading, token, function (result) {
onSuccess(result)
}, function (error) {
onFail(error)
})
}
end
最后,控制臺查看日志的示意圖為:
詳細代碼去查看github