You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
5.3 KiB
144 lines
5.3 KiB
import extend from '../../utils/extend';
|
|
import getType from '../../utils/getType';
|
|
import getTypeValue from '../../utils/getTypeValue';
|
|
import mergePath from '../../utils/mergePath';
|
|
import toast from '../../utils/toast';
|
|
import noop from './../../utils/noop';
|
|
import createError from './createError';
|
|
import createSuccess from './createSuccess';
|
|
import defaultConfig from './defaultConfig';
|
|
import defaultInterceptors from './defaultInterceptors';
|
|
import failMap from './failMap';
|
|
import loading from './loading';
|
|
|
|
/**
|
|
* @description: 创建一个请求器
|
|
* @param {defaultConfig} config 默认参数
|
|
* @param {defaultInterceptors} interceptors 拦截器
|
|
* @return {function(defaultConfig)}
|
|
*/
|
|
export default function createRequest(config = {}, interceptors = {}) {
|
|
// 配置
|
|
config = extend(true, {}, defaultConfig, config);
|
|
// 拦截器
|
|
interceptors = Object.assign({}, defaultInterceptors, interceptors);
|
|
|
|
/**
|
|
* @description: 请求方法
|
|
* @param {defaultConfig} options
|
|
* @return {Promise}
|
|
*/
|
|
const request = function request(options = {}) {
|
|
options = extend(true, {}, config, options);
|
|
// 显示loading
|
|
if (options.showLoading && options.useDefaultLoading) {
|
|
loading.show(options.loadingText, options.loadingTime);
|
|
}
|
|
// 创建 promise
|
|
const promise = new Promise((resolve, reject) => {
|
|
// 执行请求前拦截器
|
|
Promise.resolve(interceptors.request(options)).then(newOptions => {
|
|
// 获取新的options
|
|
options = getTypeValue(newOptions, Object, options);
|
|
// method转大写
|
|
options.method = options.method.toUpperCase();
|
|
// 路径参数赋值
|
|
if (options.url && options.urlParams) {
|
|
options.url = options.url.replace(/{([^{}}]+)}/g, (_str, k) => options.urlParams[k]);
|
|
}
|
|
// 判断url是否携带域名,然后拼接域名
|
|
if (!/^(https|http|\/{2})/.test(options.url)) {
|
|
options.url = mergePath(options.baseURL, options.url);
|
|
}
|
|
// 去除无效参数
|
|
if (getType(options.data) === 'object') {
|
|
const data = JSON.parse(JSON.stringify(options.data));
|
|
const isUrlParams = ['GET', 'DELETE', 'PATCH'].includes(options.method);
|
|
Object.keys(data).forEach(k => {
|
|
const value = data[k];
|
|
if ([undefined, null].includes(value)) {
|
|
// 如果属性值为undefined或null,则直接移除属性
|
|
delete data[k];
|
|
} else if (isUrlParams && typeof value === 'string' && !value.trim()) {
|
|
// 如果是'GET', 'DELETE', 'PATCH'请求方式,则移除值为空字符串的属性
|
|
delete data[k];
|
|
}
|
|
});
|
|
options.data = data;
|
|
}
|
|
// 发起请求
|
|
const createTask = () => {
|
|
options.getTask = getTypeValue(options.getTask, Function, defaultConfig.getTask);
|
|
options.validateStatus = getTypeValue(options.validateStatus, Function, defaultConfig.validateStatus);
|
|
options.getTask(uni.request(Object.assign({}, options, {
|
|
success: noop,
|
|
fail: noop,
|
|
complete(res) {
|
|
// 判断请求状态
|
|
if (options.validateStatus(res, options)) {
|
|
resolve(res.data);
|
|
} else {
|
|
const { statusCode, errMsg } = res;
|
|
let msg = failMap[statusCode];
|
|
if (!msg) {
|
|
if (errMsg.indexOf('timeout') > -1) {
|
|
msg = '请求超时';
|
|
} else if (errMsg.indexOf('request:fail') > -1) {
|
|
msg = '请求异常';
|
|
} else {
|
|
msg = errMsg;
|
|
}
|
|
}
|
|
if (statusCode) msg = statusCode + ` ${msg}`;
|
|
reject(createError(msg, statusCode));
|
|
}
|
|
},
|
|
})));
|
|
};
|
|
// 判断是否延时发起请求
|
|
if (options.delayTime > 0) {
|
|
setTimeout(createTask, options.delayTime);
|
|
} else {
|
|
createTask();
|
|
}
|
|
}).catch(error => reject(createError(error)));
|
|
}).then(
|
|
data => {
|
|
// 执行请求成功拦截器
|
|
return interceptors.success({ options, data, createError, createSuccess });
|
|
},
|
|
error => {
|
|
if (options.showError && options.useDefaultToast) {
|
|
toast({ message: error.message, duration: options.toastTime });
|
|
}
|
|
// 执行请求失败拦截器
|
|
return interceptors.fail({ options, error, createError, createSuccess });
|
|
},
|
|
).finally(() => {
|
|
// 关闭loading
|
|
if (options.showLoading && options.useDefaultLoading) {
|
|
loading.hide();
|
|
}
|
|
});
|
|
// 执行参数上的回调方法
|
|
promise.then(res => {
|
|
typeof options.success === 'function' && options.success(res);
|
|
typeof options.complete === 'function' && options.complete(res);
|
|
}).catch(err => {
|
|
typeof options.fail === 'function' && options.fail(err);
|
|
typeof options.complete === 'function' && options.complete(err);
|
|
});
|
|
// 返回 promise
|
|
return promise;
|
|
};
|
|
// 增加属性方法
|
|
['get', 'post', 'put', 'delete', 'head', 'trace', 'options', 'connect'].map(method => {
|
|
request[method] = (url, data, options) => request({
|
|
method,
|
|
url,
|
|
data,
|
|
...options,
|
|
});
|
|
});
|
|
return request;
|
|
}
|
|
|