ty-mobile-uni
Version:
uView UI,是uni-app生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
266 lines (263 loc) • 10.3 kB
JavaScript
import Vue from 'vue'
export default function ({
baseURL,
timeout = 12345,
header: headers,
statusCode = [200, 401],
}) {
return {
init(config) {
const { url, method, data, header, hideLoading } = config
if (!method || !url) return
if (method == 'uploadFile' || method == 'downloadFile') {
return this.file(method, url, data || {}, { ...header, ...headers })
}
//GET,POST,PUT,DELETE,CONNECT,HEAD,OPTIONS,TRACE
return this.request(
method,
url,
data,
{ ...header, ...headers },
hideLoading
)
},
onerror: [], // 请求错误钩子函数集合
file(method, url, data, header) {
let timer,
requestTask,
aborted = false,
abort = () => {
// timer 检测超时定时器,requestTask 网络请求 task 对象,aborted 请求是否已被取消,abort 取消请求方法
aborted = true // 将请求状态标记为已取消
requestTask ? requestTask.abort() : '' // 执行取消请求方法
},
progressUpdateHandle,
onProgressUpdate = (e) => (progressUpdateHandle = e) // progressUpdateHandle 监听上传进度变化回调,onProgressUpdate 监听上传进度变化方法
return new Proxy(
new Promise((resolve, reject) => {
// 返回经过 Proxy 后的 Promise 对象使其可以监听到是否调用 abort 和 onProgressUpdate 方法
this.interceptors.request
.intercept(
{ header: header || {}, body: data.formData || {} },
method,
url,
data
)
.then(async ({ header, body }) => {
// 等待请求拦截器里的方法执行完
if (aborted) {
// 如果请求已被取消,停止执行,返回 reject
await this.onerror(method, url, data, '网络请求失败:主动取消')
return reject('网络请求失败:主动取消')
}
const formData = { ...data }
delete formData.filePath
delete formData.name
requestTask = uni[method]({
url:
url[0] === '/'
? (baseURL || Vue.prototype.baseUrl) + url
: url,
name: data.name,
header,
formData: { ...formData }, //...body,
filePath: data.filePath,
success: async (res) => {
clearTimeout(timer)
!statusCode.includes(res.statusCode)
? await this.onerror(
method,
url,
data,
`网络请求异常:服务器响应异常:状态码:${res.statusCode}`
)
: '',
this.interceptors.response.intercept(
statusCode.includes(res.statusCode) ? resolve : reject,
{ success: statusCode.includes(res.statusCode), ...res },
method,
url,
data,
reject
) // 执行响应拦截器
},
fail: async (res) => {
clearTimeout(timer)
await this.onerror(
method,
url,
data,
aborted
? '网络请求失败:主动取消'
: '网络请求失败:(URL无效|无网络|DNS解析失败)'
)
aborted
? reject('网络请求失败:主动取消')
: reject('网络请求失败:(URL无效|无网络|DNS解析失败)')
},
})
requestTask.onProgressUpdate(progressUpdateHandle) // 监听下载进度变化
timer = setTimeout(async () => {
// 请求超时执行方法
requestTask.abort() // 执行取消请求方法
await this.onerror(method, url, data, '网络请求失败:超时取消')
reject('网络请求时间超时') // reject 原因
}, timeout) // 设定检测超时定时器
})
}),
{
get: (target, prop) => {
if (prop === 'abort') {
return abort
} else {
if (Reflect.get(target, prop) && Reflect.get(target, prop).bind) {
return Reflect.get(target, prop).bind(target)
} else {
return Reflect.get(target, prop)
}
}
},
}
) // 如果调用 cancel 方法,返回 _watcher.cancel 方法
},
request(method, url, data, header, hideLoading) {
let timer,
requestTask,
aborted = false,
abort = () => {
// timer 检测超时定时器,requestTask 网络请求 task 对象,aborted 请求是否已被取消,abort 取消请求方法
aborted = true // 将请求状态标记为已取消
requestTask ? requestTask.abort() : '' // 执行取消请求方法
}
return new Proxy(
new Promise((resolve, reject) => {
// 返回经过 Proxy 后的 Promise 对象使其可以监听到是否调用 abort 方法
this.interceptors.request
.intercept(
{
header: header || {},
body: data || {},
hideLoading: hideLoading,
},
method,
url,
data
)
.then(async ({ header, body: data }) => {
// 等待请求拦截器里的方法执行完
if (aborted) {
// 如果请求已被取消,停止执行,返回 reject
await this.onerror(method, url, data, '网络请求失败:主动取消')
return reject('网络请求失败:主动取消')
}
requestTask = uni.request({
url:
url[0] === '/'
? (baseURL || Vue.prototype.baseUrl) + url
: url,
data,
method,
header,
success: async (res) => {
// 网络请求成功
clearTimeout(timer) // 清除检测超时定时器
res.statusCode !== 200
? await this.onerror(
method,
url,
data,
`网络请求异常:服务器响应异常:状态码:${res.statusCode}`
)
: ''
this.interceptors.response.intercept(
statusCode.includes(res.statusCode) ? resolve : reject,
{ success: statusCode.includes(res.statusCode), ...res },
method,
url,
data,
reject
) // 执行响应拦截器
},
fail: async (res) => {
// 网络请求失败
clearTimeout(timer) // 清除检测超时定时器
await this.onerror(
method,
url,
data,
aborted
? '网络请求失败:主动取消'
: '网络请求失败:(URL无效|无网络|DNS解析失败)'
)
aborted
? reject('网络请求失败:主动取消')
: reject('网络请求失败:(URL无效|无网络|DNS解析失败)')
},
})
timer = setTimeout(async () => {
// 请求超时执行方法
requestTask.abort() // 执行取消请求方法
await this.onerror(method, url, data, '网络请求失败:超时取消')
reject('网络请求时间超时') // reject 原因
}, timeout || 12345) // 设定检测超时定时器
})
}),
{
get: (target, prop) => {
if (prop === 'abort') {
return abort
} else {
if (Reflect.get(target, prop) && Reflect.get(target, prop).bind) {
return Reflect.get(target, prop).bind(target)
} else {
return Reflect.get(target, prop)
}
}
},
}
) // 如果调用 abort 方法,返回 abort 方法
},
interceptors: {
// 拦截器
request: {
interceptors: [],
use(fun) {
this.interceptors.push(fun)
},
async intercept(config, method, url, data) {
for (let i = 0; i < this.interceptors.length; i++) {
config = await this.interceptors[i](config, method, url, data)
}
return config
},
},
response: {
interceptors: [],
use(fun) {
this.interceptors.push(fun)
},
async intercept(STATUS, response, method, url, data, reject) {
try {
for (let i = 0; i < this.interceptors.length; i++) {
response = await this.interceptors[i](response, method, url, data)
}
if (response && response.success) {
return STATUS(
typeof response.data === 'string'
? JSON.parse(response.data)
: response.data
)
} else {
if (response) {
delete response.success
}
return STATUS(response, method, url, data)
}
} catch (e) {
reject(e)
}
},
},
},
}
}