前言
-
剛剛接觸uni-app時候想著直接使用axios發(fā)請求,可以發(fā)送成功但是請求頭有點問題
-
后面發(fā)現(xiàn)教程都是使用@escookrequest-miniprogram三方包發(fā)送請求-(瀏覽器環(huán)境發(fā)送不了請求,不兼容)
-
為什么不直接用uni.request()發(fā)送請求,是因為每次請求都要寫一次添加請求頭不合理
-
后面隨著深入了解uni-app,發(fā)現(xiàn)開源框架,若依,芋道,都是封裝一層uni.request發(fā)請求
-
解決了統(tǒng)一添加請求頭問題,使用uni.request比較合理,自己寫可能不全面,可以直接搬
細節(jié)
1.觀察我們會發(fā)現(xiàn)在utils工具文件夾下有upload.js和request.js2個文件在發(fā)請求是都在引入
2.request.js基于uni.request封裝添加請求頭,用戶id。專門用來發(fā)送普通api請求
3.upload.js基于 uni.uploadFile封裝添加請求頭,用戶id,專門用來對接文檔服務器,上傳圖片文件
4.并不是所有接口都需要添加請求頭,在不需要添加的請求頭的接口寫isToken: false
5.uni.request發(fā)請求是兼容瀏覽器環(huán)境的,@escookrequest-miniprogram是不兼容瀏覽器發(fā)請求
代碼實現(xiàn)
1.在utils工具文件夾下分別建立request.js和upload.js文件夾-代碼如下
request.js
// 引入vuex-調用退出登錄方法
import store from '@/store'
// 引入基地址文件
import config from '@/config'
// 引入獲取token文件
import { getAccessToken } from '@/utils/auth'
// 引入轉臺碼錯誤文件
import errorCode from '@/utils/errorCode'
// 引入公共方法文件
import { toast, showConfirm, tansParams } from '@/utils/common'
?
let timeout = 10000
const baseUrl = config.baseUrl;
?
const request = config => {
// 是否需要設置 token
const isToken = (config.headers || {}).isToken === false
config.header = config.header || {}
if (getAccessToken() && !isToken) {
? config.header['Authorization'] = 'Bearer ' + getAccessToken()
}
// 設置租戶 TODO 芋艿:強制 1 先
config.header['tenant-id'] = '1';
// get請求映射params參數(shù)
if (config.params) {
? let url = config.url + '?' + tansParams(config.params)
? url = url.slice(0, -1)
? config.url = url
}
return new Promise((resolve, reject) => {
? uni.request({
? ? ? method: config.method || 'get',
? ? ? timeout: config.timeout || timeout,
? ? ? url: config.baseUrl || baseUrl + config.url,
? ? ? data: config.data,
? ? ? // header: config.header,
? ? ? header: config.header,
? ? ? dataType: 'json'
? ? }).then(response => {
? ? ? let [error, res] = response
? ? ? if (error) {
? ? ? ? toast('后端接口連接異常')
? ? ? ? reject('后端接口連接異常')
? ? ? ? return
? ? ? }
? ? ? const code = res.data.code || 200
? ? ? const msg = errorCode[code] || res.data.msg || errorCode['default']
? ? ? if (code === 401) {
? ? ? ? showConfirm('登錄狀態(tài)已過期,您可以繼續(xù)留在該頁面,或者重新登錄?').then(res => {
? ? ? ? ? if (res.confirm) {
? ? ? ? ? ? store.dispatch('LogOut').then(res => {
? ? ? ? ? ? ? uni.reLaunch({ url: '/pages/login' })
? ? ? ? ? ? })
? ? ? ? ? }
? ? ? ? })
? ? ? ? reject('無效的會話,或者會話已過期,請重新登錄。')
? ? ? } else if (code === 500) {
? ? ? ? toast(msg)
? ? ? ? reject('500')
? ? ? } else if (code !== 200) {
? ? ? ? toast(msg)
? ? ? ? reject(code)
? ? ? }
? ? ? resolve(res.data)
? ? })
? ? .catch(error => {
? ? ? let { message } = error
? ? ? if (message === 'Network Error') {
? ? ? ? message = '后端接口連接異常'
? ? ? } else if (message.includes('timeout')) {
? ? ? ? message = '系統(tǒng)接口請求超時'
? ? ? } else if (message.includes('Request failed with status code')) {
? ? ? ? message = '系統(tǒng)接口' + message.substr(message.length - 3) + '異常'
? ? ? }
? ? ? toast(message)
? ? ? reject(error)
? ? })
})
}
?
export default request
?
upload.js
// 引入vuex-調用退出登錄方法
import store from '@/store'
// 引入基地址文件
import config from '@/config'
// 引入獲取token文件
import { getAccessToken } from '@/utils/auth'
// 引入轉臺碼錯誤文件
import errorCode from '@/utils/errorCode'
// 引入公共方法文件
import { toast, showConfirm, tansParams } from '@/utils/common'
?
let timeout = 10000
const baseUrl = config.baseUrl
?
const upload = config => {
// 是否需要設置 token
const isToken = (config.headers || {}).isToken === false
config.header = config.header || {}
if (getAccessToken() && !isToken) {
? config.header['Authorization'] = 'Bearer ' + getAccessToken()
}
// get請求映射params參數(shù)
if (config.params) {
? let url = config.url + '?' + tansParams(config.params)
? url = url.slice(0, -1)
? config.url = url
}
// 設置租戶 TODO 芋艿:強制 1 先
config.header['tenant-id'] = '1';
return new Promise((resolve, reject) => {
? ? uni.uploadFile({
? ? ? timeout: config.timeout || timeout,
? ? ? url: baseUrl + config.url,
? ? ? filePath: config.filePath,
? ? ? name: config.name || 'file',
? ? ? header: config.header,
? ? ? formData: config.formData,
? ? ? method: config.method || 'post',
? ? ? success: (res) => {
? ? ? ? let result = JSON.parse(res.data)
? ? ? ? const code = result.code || 200
? ? ? ? const msg = errorCode[code] || result.msg || errorCode['default']
? ? ? ? if (code === 200) {
? ? ? ? ? resolve(result)
? ? ? ? } else if (code == 401) {
? ? ? ? ? showConfirm("登錄狀態(tài)已過期,您可以繼續(xù)留在該頁面,或者重新登錄?").then(res => {
? ? ? ? ? ? if (res.confirm) {
? ? ? ? ? ? ? store.dispatch('LogOut').then(res => {
? ? ? ? ? ? ? ? uni.reLaunch({ url: '/pages/login/login' })
? ? ? ? ? ? ? })
? ? ? ? ? ? }
? ? ? ? ? })
? ? ? ? ? reject('無效的會話,或者會話已過期,請重新登錄。')
? ? ? ? } else if (code === 500) {
? ? ? ? ? toast(msg)
? ? ? ? ? reject('500')
? ? ? ? } else if (code !== 200) {
? ? ? ? ? toast(msg)
? ? ? ? ? reject(code)
? ? ? ? }
? ? ? },
? ? ? fail: (error) => {
? ? ? ? let { message } = error
? ? ? ? if (message == 'Network Error') {
? ? ? ? ? message = '后端接口連接異常'
? ? ? ? } else if (message.includes('timeout')) {
? ? ? ? ? message = '系統(tǒng)接口請求超時'
? ? ? ? } else if (message.includes('Request failed with status code')) {
? ? ? ? ? message = '系統(tǒng)接口' + message.substr(message.length - 3) + '異常'
? ? ? ? }
? ? ? ? toast(message)
? ? ? ? reject(error)
? ? ? }
? ? })
})
}
?
export default upload
?
2.在最外層與utils.js同級下創(chuàng)建基地址文件config.js
// 應用全局配置
module.exports = {
baseUrl: '基地址',
// 應用信息
appInfo: {
? // 應用名稱
? name: "app",
? // 應用版本
? version: "1.0.0",
? // 應用logo
? logo: "/static/logo.png",
? // 官方網站
? site_url: "",
? // 政策協(xié)議
? agreements: [{
? ? ? title: "隱私政策",
? ? ? url: ""
? ? },
? ? {
? ? ? title: "用戶服務協(xié)議",
? ? ? url: ""
? ? }
? ]
}
}
?
3.在utils.js工具文件下創(chuàng)建auth.js文件-存儲token
RefreshTokenKey-是用來補救token失效換取token的一種無感刷新形式沒有不用管
const AccessTokenKey = 'ACCESS_TOKEN'
const RefreshTokenKey = 'REFRESH_TOKEN'
?
// ========== Token 相關 ==========
?
export function getAccessToken() {
return uni.getStorageSync(AccessTokenKey)
}
?
export function getRefreshToken() {
return uni.getStorageSync(RefreshTokenKey)
}
?
export function setToken(token) {
uni.setStorageSync(AccessTokenKey, token.accessToken)
uni.setStorageSync(RefreshTokenKey, token.refreshToken)
}
?
export function removeToken() {
uni.removeStorageSync(AccessTokenKey)
uni.removeStorageSync(RefreshTokenKey)
}
?
4.在utils.js工具文件下創(chuàng)建errorCode.js文件-狀態(tài)碼錯誤文件
export default {
'401': '認證失敗,無法訪問系統(tǒng)資源',
'403': '當前操作沒有權限',
'404': '訪問資源不存在',
'default': '系統(tǒng)未知錯誤,請反饋給管理員'
}
?
5.在utils.js工具文件下創(chuàng)建common.js文件-公共方法
/**
* 顯示消息提示框
* @param content 提示的標題
*/
export function toast(content) {
uni.showToast({
? icon: 'none',
? title: content
})
}
?
/**
* 顯示模態(tài)彈窗
* @param content 提示的標題
*/
export function showConfirm(content) {
return new Promise((resolve, reject) => {
? uni.showModal({
? ? title: '提示',
? ? content: content,
? ? cancelText: '取消',
? ? confirmText: '確定',
? ? success: function(res) {
? ? ? resolve(res)
? ? }
? })
})
}
?
/**
* 參數(shù)處理
* @param params 參數(shù)
*/
export function tansParams(params) {
let result = ''
for (const propName of Object.keys(params)) {
? const value = params[propName]
? var part = encodeURIComponent(propName) + "="
? if (value !== null && value !== "" && typeof (value) !== "undefined") {
? ? if (typeof value === 'object') {
? ? ? for (const key of Object.keys(value)) {
? ? ? ? if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
? ? ? ? ? let params = propName + '[' + key + ']'
? ? ? ? ? var subPart = encodeURIComponent(params) + "="
? ? ? ? ? result += subPart + encodeURIComponent(value[key]) + "&"
? ? ? ? }
? ? ? }
? ? } else {
? ? ? result += part + encodeURIComponent(value) + "&"
? ? }
? }
}
return result
}
5.在utils.js工具文件下創(chuàng)建permission.js文件-導航守衛(wèi)設置白名單,頁面攔截器
import { getAccessToken } from '@/utils/auth'
?
// 登錄頁面
const loginPage = "/pages/login"
?
// 頁面白名單
const whiteList = [
'/pages/login', '/pages/common/webview/index'
]
?
// 檢查地址白名單
function checkWhite(url) {
const path = url.split('?')[0]
return whiteList.indexOf(path) !== -1
}
?
// 頁面跳轉驗證攔截器
let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]
list.forEach(item => {
uni.addInterceptor(item, {
? invoke(to) {
? ? if (getAccessToken()) {
? ? ? if (to.path === loginPage) {
? ? ? ? uni.reLaunch({ url: "/" })
? ? ? }
? ? ? return true
? ? } else {
? ? ? if (checkWhite(to.url)) {
? ? ? ? return true
? ? ? }
? ? ? uni.reLaunch({ url: loginPage })
? ? ? return false
? ? }
? },
? fail(err) {
? ? console.log(err)
? }
})
})
?
6.在main.js中引入導航守衛(wèi)文件
// permission
// 導航守衛(wèi)文件
import './permission'
7.發(fā)送請求例子
// 對接文檔服務器封裝
import upload from '@/utils/upload'
// 對接普通api接口
import request from '@/utils/request'
?
// 登錄方法-不需要添加token-請求頭添加isToken: false
export function login(username, password, captchaVerification) {
const data = {
username,
password,
captchaVerification
}
return request({
url: '/system/auth/login',
headers: {
isToken: false
},
'method': 'POST',
'data': data
})
}
?
// 查詢用戶個人信息-普通api添加token+用戶id
export function getUserProfile() {
return request({
? url: '/system/user/profile/get',
? method: 'GET'
})
}
?
// 用戶頭像上傳-對接文檔服務器
export function uploadAvatar(data) {
return upload({
? url: '/system/user/profile/update-avatar',
? method: 'PUT',
? name: data.name,
? filePath: data.filePath
})
}
總結:
經過這一趟流程下來相信你也對 uni-app 使用uni.request封裝發(fā)送api請求文檔服務器請求導航守衛(wèi) 有了初步的深刻印象,但在實際開發(fā)中我 們遇到的情況肯定是不一樣的,所以我們要理解它的原理,萬變不離其宗。加油,打工人!文章來源:http://www.zghlxwxcb.cn/news/detail-603339.html
什么不足的地方請大家指出謝謝 -- 風過無痕文章來源地址http://www.zghlxwxcb.cn/news/detail-603339.html
到了這里,關于uni-app 使用uni.request封裝發(fā)送api請求文檔服務器請求導航守衛(wèi)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!