This commit is contained in:
TENCENT\ivinwu
2018-12-19 19:26:38 +08:00
parent a7ee72b26c
commit 103647984e
25 changed files with 1672 additions and 1275 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,28 @@
{
"name": "weRequest",
"version": "1.0.0",
"version": "1.1.0",
"description": "本工具通过拓展小程序的wx.request让开发者通过简单的配置实现自动管理登录态等功能",
"main": "./src/weRequest.js",
"keywords": [
"登录态",
"登陆态",
"会话管理",
"用户态",
"小程序"
],
"homepage": "https://github.com/IvinWu/weRequest",
"author": {
"name": "Ivin Wu",
"email": "ivinwu@tencent.com",
"url": "https://github.com/IvinWu"
},
"repository": {
"type": "git",
"url": "https://github.com/IvinWu/weRequest.git"
},
"main": "./src/index.js",
"scripts": {
"build": "webpack"
},
"dependencies": {
"webpack": "latest"
},

11
src/api/getConfig.js Normal file
View File

@@ -0,0 +1,11 @@
import config from '../store/config'
import status from '../store/status'
export default () => {
return {
urlPerfix: config.urlPerfix,
sessionExpireTime: status.sessionExpireTime,
sessionExpireKey: config.sessionExpireKey,
sessionExpire: status.sessionExpire
}
};

5
src/api/getSession.js Normal file
View File

@@ -0,0 +1,5 @@
import status from '../store/status'
export default () => {
return status.session
}

22
src/api/init.js Normal file
View File

@@ -0,0 +1,22 @@
import config from '../store/config'
import status from '../store/status'
export default (params) => {
Object.assign(config, params);
// 如果配置更改了session的存储名字则重新获取一次session
if (params.sessionName) {
try {
status.session = wx.getStorageSync(config.sessionName) || '';
} catch (e) {
console.error('wx.getStorageSync:fail, can not get session.')
}
}
// 如果配置更改了session过期时间的存储名字则重新获取一次session的过期时间
if (params.sessionExpireKey) {
try {
status.sessionExpire = wx.getStorageSync(config.sessionExpireKey) || Infinity;
} catch (e) {
console.error('wx.getStorageSync:fail, can not get sessionExpire.')
}
}
}

5
src/api/login.js Normal file
View File

@@ -0,0 +1,5 @@
import sessionManager from '../module/sessionManager'
export default (callback) => {
sessionManager(callback, {})
}

5
src/api/request.js Normal file
View File

@@ -0,0 +1,5 @@
import requestHandler from '../module/requestHandler'
export default (obj) => {
requestHandler.request(obj)
}

6
src/api/setSession.js Normal file
View File

@@ -0,0 +1,6 @@
import status from '../store/status'
export default (session) => {
status.session = session;
status.sessionIsFresh = true;
}

5
src/api/uploadFile.js Normal file
View File

@@ -0,0 +1,5 @@
import requestHandler from '../module/requestHandler'
export default (obj) => {
requestHandler.uploadFile(obj)
}

17
src/index.js Normal file
View File

@@ -0,0 +1,17 @@
import init from './api/init'
import request from './api/request'
import uploadFile from './api/uploadFile'
import setSession from './api/setSession'
import login from './api/login'
import getSession from './api/getSession'
import getConfig from './api/getConfig'
export {
init,
request,
uploadFile,
setSession,
login,
getSession,
getConfig
}

View File

@@ -1,31 +0,0 @@
var store = {};
function emit (key){
var flow = getFlow(key);
console.log("waitingList Length: " + flow.waitingList.length);
var currentLength = flow.waitingList.length;
for (var i = 0; i < currentLength; i ++) {
var callback = flow.waitingList.shift();
typeof callback == "function" && callback();
}
}
function wait (key,callback){
var flow = getFlow(key);
flow.waitingList.push(callback)
}
function getFlow(key){
if(!store[key]){
store[key] = {
waitingList:[]
}
}
return store[key];
}
module.exports = {
wait: wait,
emit: emit
}

View File

@@ -0,0 +1,31 @@
function get(obj) {
wx.getStorage({
key: obj.originUrl,
success: function (res) {
if (typeof obj.cache === "function" && obj.cache(res.data)) {
if (typeof obj.success === "function") {
obj.success(res.data, {isCache: true})
}
} else if (obj.cache == true) {
if (typeof obj.success === "function") {
obj.success(res.data, {isCache: true})
}
}
typeof obj.complete === "function" && obj.complete();
}
})
}
function set(obj, realData) {
if (obj.cache === true || (typeof obj.cache === "function" && obj.cache(realData))) {
wx.setStorage({
key: obj.originUrl,
data: realData
})
}
}
export default {
get,
set
};

View File

@@ -0,0 +1,47 @@
import config from '../store/config'
function start(obj, name) {
switch (name) {
case 'checkSession':
obj._checkSessionStartTime = new Date().getTime();
break;
case 'login':
obj._loginStartTime = new Date().getTime();
break;
default:
if (obj.report) {
obj._reportStartTime = new Date().getTime();
}
}
}
function end(obj, name) {
switch (name) {
case 'checkSession':
// wx.checkSession 耗时上报
obj._checkSessionEndTime = new Date().getTime();
if (typeof config.reportCGI === "function") {
config.reportCGI('wx_checkSession', obj._checkSessionStartTime, obj._checkSessionEndTime);
}
break;
case 'login':
// wx.login 耗时上报
obj._loginEndTime = new Date().getTime();
if (typeof config.reportCGI === "function") {
config.reportCGI('wx_login', obj._loginStartTime, obj._loginEndTime);
}
break;
default:
// 其他CGI接口
if (obj.report && typeof config.reportCGI === "function") {
obj._reportEndTime = new Date().getTime();
config.reportCGI(obj.report, obj._reportStartTime, obj._reportEndTime);
}
break;
}
}
export default {
start,
end
}

View File

@@ -0,0 +1,40 @@
import config from '../store/config'
export default (obj, res) => {
if (typeof obj.fail === "function") {
obj.fail(res);
} else {
let title = "";
if (typeof config.errorTitle === "function") {
try {
title = config.errorTitle(res.data)
} catch (e) {
}
} else if (typeof errorTitle === "string") {
title = config.errorTitle;
}
let content = "";
if (typeof config.errorContent === "function") {
try {
content = config.errorContent(res.data)
} catch (e) {
}
} else if (typeof config.errorContent === "string") {
content = config.errorContent;
}
wx.showModal({
title: title,
content: content || "网络或服务异常,请稍后重试",
showCancel: false
})
}
// 如果有配置统一错误回调函数,则执行它
if (typeof config.errorCallback === "function") {
config.errorCallback(obj, res);
}
console.error(res);
}

25
src/module/mockManager.js Normal file
View File

@@ -0,0 +1,25 @@
import config from '../store/config'
import responseHandler from './responseHandler'
function get(obj, method) {
if(!config.mockJson[obj.url] && !config.mockJson[obj.originUrl]) {
// mock 没有对应接口的数据
console.error('mock 没有对应接口的数据');
return false;
}
let data = config.mockJson[obj.url] || config.mockJson[obj.originUrl];
// deep copy
data = JSON.parse(JSON.stringify(data));
let res = {
data: data,
statusCode: 200
};
responseHandler(res, obj, method)
}
export default {
get
}

View File

@@ -0,0 +1,182 @@
import loading from '../util/loading'
import config from '../store/config'
import status from '../store/status'
import mockManager from './mockManager'
import cacheManager from './cacheManager'
import sessionManager from './sessionManager'
import errorHandler from './errorHandler'
import responseHandler from './responseHandler'
import durationReporter from "./durationReporter";
// 格式化url
function format(url) {
if (url.startsWith('http')) {
return url
} else {
let urlPerfix = config.urlPerfix;
if (typeof config.urlPerfix === "function") {
urlPerfix = config.urlPerfix()
}
return urlPerfix + url;
}
}
// 所有请求发出前需要做的事情
function preDo(obj) {
if(typeof obj.beforeSend === "function") {
obj.beforeSend();
}
// 登录态失效,重复登录计数
if (typeof obj.reLoginLimit === "undefined") {
obj.reLoginLimit = 0;
} else {
obj.reLoginLimit++;
}
if (typeof obj.count === "undefined") {
obj.count = 0;
}
if (obj.showLoading) {
loading.show(obj.showLoading);
obj.complete = ((fn) => {
return ()=> {
loading.hide();
typeof fn === "function" && fn.apply(this, arguments);
}
})(obj.complete)
}
obj.originUrl = obj.url;
obj.url = format(obj.url);
return obj;
}
// 格式化处理请求的obj内容
function initialize(obj, container) {
if (!obj[container]) {
obj[container] = {};
}
if (obj.originUrl !== config.codeToSession.url && status.session) {
obj[container][config.sessionName] = status.session;
}
// 如果有全局参数,则添加
let gd = {};
if (typeof config.globalData === "function") {
gd = config.globalData();
} else if (typeof config.globalData === "object") {
gd = config.globalData;
}
obj[container] = Object.assign({}, gd, obj[container]);
obj.method = obj.method || 'GET';
obj.dataType = obj.dataType || 'json';
// 如果请求不是GET则在URL中自动加上登录态和全局参数
if (obj.method !== "GET") {
if (status.session) {
if (obj.url.indexOf('?') >= 0) {
obj.url += '&' + config.sessionName + '=' + encodeURIComponent(status.session);
} else {
obj.url += '?' + config.sessionName + '=' + encodeURIComponent(status.session);
}
}
// 如果有全局参数则在URL中添加
for (let i in gd) {
if (obj.url.indexOf('?') >= 0) {
obj.url += '&' + i + '=' + gd[i];
} else {
obj.url += '?' + i + '=' + gd[i];
}
}
}
durationReporter.start(obj);
return obj;
}
function doRequest(obj) {
obj = initialize(obj, 'data');
obj.count++;
wx.request({
url: obj.url,
data: obj.data,
method: obj.method,
header: obj.header || {},
dataType: obj.dataType || 'json',
success: function (res) {
responseHandler(res, obj, 'request')
},
fail: function (res) {
errorHandler(obj, res);
console.error(res);
},
complete: function () {
obj.count--;
typeof obj.complete === "function" && obj.count === 0 && obj.complete();
}
})
}
function doUploadFile(obj) {
obj.count++;
wx.uploadFile({
url: obj.url,
filePath: obj.filePath || '',
name: obj.name || '',
method: 'POST',
formData: obj.formData,
success: function (res) {
responseHandler(res, obj, 'uploadFile')
},
fail: function (res) {
errorHandler(obj, res);
console.error(res);
},
complete: function () {
obj.count--;
typeof obj.complete === "function" && obj.count === 0 && obj.complete();
}
})
}
function request(obj) {
obj = preDo(obj);
if(config.mockJson) {
mockManager.get(obj, 'request');
return false;
}
if(obj.cache) {
cacheManager.get(obj);
}
sessionManager(()=>{
doRequest(obj)
}, obj)
}
function uploadFile(obj) {
obj = preDo(obj);
if(config.mockJson) {
mockManager.get(obj, 'uploadFile');
return false;
}
if(obj.cache) {
cacheManager.get(obj);
}
sessionManager(()=>{
doUploadFile(obj)
}, obj)
}
export default {
request,
uploadFile
}

View File

@@ -0,0 +1,68 @@
import config from '../store/config'
import status from '../store/status'
import requestHandler from './requestHandler'
import errorHandler from './errorHandler'
import cacheManager from './cacheManager'
import durationReporter from './durationReporter'
function response(res, obj, method) {
if (res.statusCode === 200) {
// 兼容uploadFile返回的res.data可能是字符串
if(typeof res.data === "string") {
try {
res.data = JSON.parse(res.data);
} catch (e) {
errorHandler(obj, res);
return false;
}
}
durationReporter.end(obj);
if (obj.isLogin) {
// 登录请求
let s = "";
try {
s = config.codeToSession.success(res.data);
} catch (e) {
}
if (s) {
obj.success(s);
} else {
errorHandler(obj, res);
}
} else if (config.loginTrigger(res.data) && obj.reLoginLimit < config.reLoginLimit) {
// 登录态失效,且重试次数不超过配置
status.session = '';
status.sessionIsFresh = true;
wx.removeStorage({
key: config.sessionName,
complete: function () {
requestHandler[method](obj)
}
})
} else if (config.successTrigger(res.data) && typeof obj.success === "function") {
// 接口返回成功码
let realData = null;
try {
realData = config.successData(res.data);
} catch (e) {
console.error("Function successData occur error: " + e);
}
if(!obj.noCacheFlash) {
// 如果为了保证页面不闪烁,则不回调,只是缓存最新数据,待下次进入再用
obj.success(realData);
}
// 缓存存储
cacheManager.set(obj, realData);
} else {
// 接口返回失败码
errorHandler(obj, res);
}
} else {
errorHandler(obj, res);
}
}
export default response;

View File

@@ -0,0 +1,137 @@
import flow from '../util/flow'
import status from '../store/status'
import config from '../store/config'
import requestHandler from './requestHandler'
import errorHandler from './errorHandler'
import durationReporter from './durationReporter'
function checkSession(callback, obj) {
if (status.isCheckingSession) {
flow.wait('checkSessionFinished', () => {
checkSession(callback, obj)
})
} else if (!status.sessionIsFresh && status.session) {
// 如果本地有登录态但还没检验过session_key是否有效则需要检验一次
status.isCheckingSession = true;
obj.count++;
durationReporter.start(obj, 'checkSession');
wx.checkSession({
success: function () {
// 登录态有效,且在本生命周期内无须再检验了
status.sessionIsFresh = true;
},
fail: function () {
// 登录态过期
status.session = '';
},
complete: function () {
status.isCheckingSession = false;
obj.count--;
durationReporter.end(obj, 'checkSession');
doLogin(callback, obj);
flow.emit('checkSessionFinished');
}
})
} else {
// 已经检验过了
doLogin(callback, obj);
}
}
function doLogin(callback, obj) {
if (obj.isLogin) {
// 登录接口,直接放过
typeof callback === "function" && callback();
} else if (status.session) {
// 缓存中有session
if (status.sessionExpireTime && new Date().getTime() > status.sessionExpire) {
// 如果有设置本地session缓存时间且缓存时间已到
status.session = '';
doLogin(callback, obj);
} else {
typeof callback === "function" && callback();
}
} else if (status.logining) {
// 正在登录中,请求轮询稍后,避免重复调用登录接口
flow.wait('doLoginFinished', function () {
doLogin(callback, obj);
})
} else {
// 缓存中无session
status.logining = true;
obj.count++;
durationReporter.start(obj, 'login');
console.log('wx.login');
wx.login({
complete: function () {
obj.count--;
durationReporter.end(obj, 'login');
typeof obj.complete === "function" && obj.count === 0 && obj.complete();
},
success: function (res) {
if (res.code) {
code2Session(obj, res.code, callback)
} else {
errorHandler(obj, res);
console.error(res);
// 登录失败,解除锁,防止死锁
status.logining = false;
flow.emit('doLoginFinished');
}
},
fail: function (res) {
errorHandler(obj, res);
console.error(res);
// 登录失败,解除锁,防止死锁
status.logining = false;
flow.emit('doLoginFinished');
}
})
}
}
function code2Session(obj, code, callback) {
let data;
// codeToSession.data支持函数
if (typeof config.codeToSession.data === "function") {
data = config.codeToSession.data();
} else {
data = config.codeToSession.data || {};
}
data[config.codeToSession.codeName] = code;
obj.count++;
requestHandler.request({
url: config.codeToSession.url,
data: data,
method: config.codeToSession.method || 'GET',
isLogin: true,
report: config.codeToSession.report || config.codeToSession.url,
success: function (s) {
status.session = s;
status.sessionIsFresh = true;
// 如果有设置本地session过期时间
if (status.sessionExpireTime) {
status.sessionExpire = new Date().getTime() + status.sessionExpireTime;
wx.setStorage({
key: config.sessionExpireKey,
data: status.sessionExpire
})
}
typeof callback === "function" && callback();
wx.setStorage({
key: config.sessionName,
data: status.session
})
},
complete: function () {
obj.count--;
typeof obj.complete === "function" && obj.count === 0 && obj.complete();
status.logining = false;
flow.emit('doLoginFinished');
},
fail: config.codeToSession.fail || null
})
}
export default checkSession;

26
src/store/config.js Normal file
View File

@@ -0,0 +1,26 @@
export default {
sessionName: "session",
loginTrigger() {
return false
},
codeToSession: {},
successTrigger() {
return true
},
urlPerfix: "",
successData(res) {
return res
},
doNotCheckSession: false,
errorTitle: "操作失败",
errorContent(res) {
return res
},
reLoginLimit: 3,
errorCallback: null,
reportCGI: false,
mockJson: false,
globalData: false,
// session在本地缓存的key
sessionExpireKey: "sessionExpireKey"
}

12
src/store/status.js Normal file
View File

@@ -0,0 +1,12 @@
export default {
session: '',
// session在本地缓存的有效时间
sessionExpireTime: null,
// session过期的时间点
sessionExpire: Infinity,
sessionIsFresh: false,
// 正在登录中,其他请求轮询稍后,避免重复调用登录接口
logining: false,
// 正在查询session有效期中避免重复调用接口
isCheckingSession: false
}

30
src/util/flow.js Normal file
View File

@@ -0,0 +1,30 @@
let store = {};
function emit(key) {
let flow = getFlow(key);
let currentLength = flow.waitingList.length;
for (let i = 0; i < currentLength; i++) {
let callback = flow.waitingList.shift();
typeof callback == "function" && callback();
}
}
function wait(key, callback) {
var flow = getFlow(key);
flow.waitingList.push(callback)
}
function getFlow(key) {
if (!store[key]) {
store[key] = {
waitingList: []
}
}
return store[key];
}
export default {
wait,
emit
}

View File

@@ -11,7 +11,7 @@ function hide() {
wx.hideToast();
}
module.exports = {
show: show,
hide: hide
export default {
show,
hide
}

View File

@@ -1,596 +0,0 @@
const loading = require('./loading');
const flow = require('./lib/flow');
//params
var sessionName = "session";
var loginTrigger = function () {
return false
};
var codeToSession = {};
var successTrigger = function () {
return true
};
var urlPerfix = "";
var successData = function (res) {
return res
};
var errorTitle = "操作失败";
var errorContent = function (res) {
return res
};
var reLoginLimit = 3;
var errorCallback = null;
var reportCGI = false;
var mockJson = false;
var globalData = false;
// session在本地缓存的有效时间
var sessionExpireTime = null;
// session在本地缓存的key
var sessionExpireKey = "sessionExpireKey";
// session过期的时间点
var sessionExpire = Infinity;
//global data
var session = '';
var sessionIsFresh = false;
// 正在登录中,其他请求轮询稍后,避免重复调用登录接口
var logining = false;
// 正在查询session有效期中避免重复调用接口
var isCheckingSession = false;
function checkSession(callback, obj) {
if (isCheckingSession) {
flow.wait('checkSessionFinished', function () {
checkSession(callback, obj)
})
} else if (!sessionIsFresh && session) {
isCheckingSession = true;
obj.count++;
// 如果还没检验过session是否有效则需要检验一次
obj._checkSessionStartTime = new Date().getTime();
console.log('wx.checkSession');
wx.checkSession({
success: function () {
// 登录态有效,且在本生命周期内无须再检验了
sessionIsFresh = true;
},
fail: function () {
// 登录态过期
session = '';
},
complete: function () {
isCheckingSession = false;
obj.count--;
obj._checkSessionEndTime = new Date().getTime();
if (typeof reportCGI === "function") {
reportCGI('wx_checkSession', obj._checkSessionStartTime, obj._checkSessionEndTime, request);
}
doLogin(callback, obj);
flow.emit('checkSessionFinished');
}
})
} else {
// 已经检验过了
doLogin(callback, obj);
}
}
function doLogin(callback, obj) {
if (obj.isLogin) {
// 登录接口,直接放过
typeof callback === "function" && callback();
} else if(session) {
// 缓存中有session
if(sessionExpireTime && new Date().getTime() > sessionExpire) {
// 如果有设置本地session缓存时间且缓存时间已到
session = '';
doLogin(callback, obj);
} else {
typeof callback === "function" && callback();
}
} else if (logining) {
// 正在登录中,请求轮询稍后,避免重复调用登录接口
flow.wait('doLoginFinished', function () {
doLogin(callback, obj);
})
} else {
// 缓存中无session
logining = true;
obj.count++;
// 记录调用wx.login前的时间戳
obj._loginStartTime = new Date().getTime();
console.log('wx.login');
wx.login({
complete: function () {
obj.count--;
// 记录wx.login返回数据后的时间戳用于上报
obj._loginEndTime = new Date().getTime();
if (typeof reportCGI === "function") {
reportCGI('wx_login', obj._loginStartTime, obj._loginEndTime, request);
}
typeof obj.complete === "function" && obj.count == 0 && obj.complete();
},
success: function (res) {
if (res.code) {
var data;
// codeToSession.data支持函数
if (typeof codeToSession.data === "function") {
data = codeToSession.data();
} else {
data = codeToSession.data || {};
}
data[codeToSession.codeName] = res.code;
obj.count++;
requestWrapper({
url: codeToSession.url,
data: data,
method: codeToSession.method,
isLogin: true,
report: codeToSession.report || codeToSession.url,
success: function (s) {
session = s;
sessionIsFresh = true;
// 如果有设置本地session过期时间
if(sessionExpireTime) {
sessionExpire = new Date().getTime() + sessionExpireTime;
wx.setStorage({
key: sessionExpireKey,
data: sessionExpire
})
}
typeof callback === "function" && callback();
wx.setStorage({
key: sessionName,
data: session
})
},
complete: function () {
obj.count--;
typeof obj.complete === "function" && obj.count == 0 && obj.complete();
logining = false;
flow.emit('doLoginFinished');
},
fail: codeToSession.fail || null
});
} else {
fail(obj, res);
console.error(res);
// 登录失败,解除锁,防止死锁
logining = false;
flow.emit('doLoginFinished');
}
},
fail: function (res) {
fail(obj, res);
console.error(res);
// 登录失败,解除锁,防止死锁
logining = false;
flow.emit('doLoginFinished');
}
})
}
}
function preDo(obj) {
typeof obj.beforeSend === "function" && obj.beforeSend();
// 登录态失效,重复登录计数
if (typeof obj.reLoginLimit === "undefined") {
obj.reLoginLimit = 0;
} else {
obj.reLoginLimit++;
}
if (typeof obj.count === "undefined") {
obj.count = 0;
}
if (obj.showLoading) {
loading.show(obj.showLoading);
obj.complete = (function (fn) {
return function () {
loading.hide();
typeof fn === "function" && fn.apply(this, arguments);
}
})(obj.complete)
}
return obj;
}
function request(obj) {
obj.count++;
if (!obj.data) {
obj.data = {};
}
if (obj.url != codeToSession.url && session) {
obj.data[sessionName] = session;
}
// 如果有全局参数,则添加
var gd = {};
if (typeof globalData === "function") {
gd = globalData();
} else if (typeof globalData === "object") {
gd = globalData;
}
obj.data = Object.assign({}, gd, obj.data);
obj.method = obj.method || 'GET';
// 如果请求的URL中不是http开头的则自动添加配置中的前缀
var url = obj.url.startsWith('http') ? obj.url : ((typeof urlPerfix === "function" ? urlPerfix() : urlPerfix) + obj.url);
// 如果请求不是GET则在URL中自动加上登录态和全局参数
if (obj.method != "GET") {
if (session) {
if (url.indexOf('?') >= 0) {
url += '&' + sessionName + '=' + encodeURIComponent(session);
} else {
url += '?' + sessionName + '=' + encodeURIComponent(session);
}
}
// 如果有全局参数则在URL中添加
for (var i in gd) {
if (url.indexOf('?') >= 0) {
url += '&' + i + '=' + gd[i];
} else {
url += '?' + i + '=' + gd[i];
}
}
}
// 如果有上报字段配置,则记录请求发出前的时间戳
if (obj.report) {
obj._reportStartTime = new Date().getTime();
}
wx.request({
url: url,
data: obj.data,
method: obj.method,
header: obj.header || {},
dataType: obj.dataType || 'json',
success: function (res) {
if (res.statusCode == 200) {
// 如果有上报字段配置,则记录请求返回后的时间戳,并进行上报
if (obj.report && typeof reportCGI === "function") {
obj._reportEndTime = new Date().getTime();
reportCGI(obj.report, obj._reportStartTime, obj._reportEndTime, request);
}
if (obj.isLogin) {
// 登录请求
var s = "";
try {
s = codeToSession.success(res.data);
} catch (e) {
}
if (s) {
obj.success(s);
} else {
fail(obj, res);
}
} else if (loginTrigger(res.data) && obj.reLoginLimit < reLoginLimit) {
// 登录态失效,且重试次数不超过配置
session = '';
wx.removeStorage({
key: sessionName,
complete: function () {
doLogin(function () {
requestWrapper(obj);
}, obj)
}
})
} else if (successTrigger(res.data) && typeof obj.success === "function") {
// 接口返回成功码
var realData = null;
try {
realData = successData(res.data);
} catch (e) {
console.error("Function successData occur error: " + e);
}
if(!obj.noCacheFlash) {
// 如果为了保证页面不闪烁,则不回调,只是缓存最新数据,待下次进入再用
obj.success(realData);
}
if (obj.cache === true || (typeof obj.cache === "function" && obj.cache(realData))) {
wx.setStorage({
key: obj.url,
data: realData
})
}
} else {
// 接口返回失败码
fail(obj, res);
}
} else {
fail(obj, res);
}
},
fail: function (res) {
fail(obj, res);
console.error(res);
},
complete: function () {
obj.count--;
typeof obj.complete === "function" && obj.count == 0 && obj.complete();
}
})
}
function uploadFile(obj) {
obj.count++;
if (!obj.formData) {
obj.formData = {};
}
obj.formData[sessionName] = session;
// 如果有全局参数,则添加
var gd = {};
if (typeof globalData === "function") {
gd = globalData();
} else if (typeof globalData === "object") {
gd = globalData;
}
obj.formData = Object.assign({}, gd, obj.formData);
obj.dataType = obj.dataType || 'json';
// 如果请求的URL中不是http开头的则自动添加配置中的前缀
var url = obj.url.startsWith('http') ? obj.url : ((typeof urlPerfix === "function" ? urlPerfix() : urlPerfix) + obj.url);
// 在URL中自动加上登录态和全局参数
if (session) {
if (url.indexOf('?') >= 0) {
url += '&' + sessionName + '=' + session;
} else {
url += '?' + sessionName + '=' + session;
}
}
// 如果有全局参数则在URL中添加
for (var i in gd) {
if (url.indexOf('?') >= 0) {
url += '&' + i + '=' + gd[i];
} else {
url += '?' + i + '=' + gd[i];
}
}
// 如果有上报字段配置,则记录请求发出前的时间戳
if (obj.report) {
obj._reportStartTime = new Date().getTime();
}
wx.uploadFile({
url: url,
filePath: obj.filePath || '',
name: obj.name || '',
formData: obj.formData,
success: function (res) {
if (res.statusCode == 200 && res.errMsg == 'uploadFile:ok') {
// 如果有上报字段配置,则记录请求返回后的时间戳,并进行上报
if (obj.report && typeof reportCGI === "function") {
obj.endTime = new Date().getTime();
reportCGI(obj.report, obj._reportStartTime, obj._reportEndTime, request);
}
if (obj.dataType == 'json') {
try {
res.data = JSON.parse(res.data);
} catch (e) {
fail(obj, res);
return false;
}
}
if (loginTrigger(res.data) && obj.reLoginLimit < reLoginLimit) {
// 登录态失效,且重试次数不超过配置
session = '';
wx.removeStorage({
key: sessionName,
complete: function () {
doLogin(function () {
uploadFileWrapper(obj);
}, obj)
}
})
} else if (successTrigger(res.data) && typeof obj.success === "function") {
// 接口返回成功码
obj.success(successData(res.data));
} else {
// 接口返回失败码
fail(obj, res);
}
} else {
fail(obj, res);
}
},
fail: function (res) {
fail(obj, res);
console.error(res);
},
complete: function () {
obj.count--;
typeof obj.complete === "function" && obj.count == 0 && obj.complete();
}
})
}
function fail(obj, res) {
if (typeof obj.fail === "function") {
obj.fail(res);
} else {
var title = "";
if (typeof errorTitle === "function") {
try {
title = errorTitle(res.data)
} catch (e) {
}
} else if (typeof errorTitle === "string") {
title = errorTitle;
}
var content = "";
if (typeof errorContent === "function") {
try {
content = errorContent(res.data)
} catch (e) {
}
} else if (typeof errorContent === "string") {
content = errorContent;
}
wx.showModal({
title: title,
content: content || "网络或服务异常,请稍后重试",
showCancel: false
})
}
// 如果有配置统一错误回调函数,则执行它
if (typeof errorCallback === "function") {
errorCallback(obj, res);
}
console.error(res);
}
function getCache(obj, callback) {
if (obj.cache) {
wx.getStorage({
key: obj.url,
success: function (res) {
typeof obj.beforeSend === "function" && obj.beforeSend();
if (typeof obj.cache === "function" && obj.cache(res.data)) {
typeof obj.success === "function" && obj.success(res.data, {isCache: true});
} else if (obj.cache == true) {
typeof obj.success === "function" && obj.success(res.data, {isCache: true});
}
typeof obj.complete === "function" && obj.complete();
// 成功取出缓存,还要去请求拿最新的再存起来
callback(obj);
},
fail: function() {
// 找不到缓存,直接发起请求,且不再防止页面闪烁(本来就没缓存了,更不存在更新页面导致的闪烁)
obj.noCacheFlash = false;
callback(obj);
}
})
} else {
callback(obj);
}
}
function login(callback) {
checkSession(callback, {})
}
function init(params) {
sessionName = params.sessionName || 'session';
loginTrigger = params.loginTrigger || function () {
return false
};
codeToSession = params.codeToSession || {};
successTrigger = params.successTrigger || function () {
return true
};
urlPerfix = params.urlPerfix || "";
successData = params.successData || function (res) {
return res
};
errorTitle = params.errorTitle || "操作失败";
errorContent = params.errorContent || false;
reLoginLimit = params.reLoginLimit || 3;
errorCallback = params.errorCallback || null;
sessionIsFresh = params.doNotCheckSession || false;
reportCGI = params.reportCGI || false;
mockJson = params.mockJson || false;
globalData = params.globalData || false;
sessionExpireTime = params.sessionExpireTime || null;
sessionExpireKey = params.sessionExpireKey || "sessionExpireKey";
try {
session = wx.getStorageSync(sessionName) || '';
sessionExpire = wx.getStorageSync(sessionExpireKey) || Infinity;
// 如果有设置本地session过期时间且验证已过期则直接清空session
if(new Date().getTime() > sessionExpire) {
session = '';
}
} catch (e) {
}
}
function requestWrapper(obj) {
obj = preDo(obj);
if (mockJson && (mockJson[obj.url] || mockJson[urlPerfix + obj.url])) {
// mock 模式
mock(obj);
} else {
getCache(obj, function (obj) {
checkSession(function () {
request(obj);
}, obj)
}
)
}
}
function uploadFileWrapper(obj) {
obj = preDo(obj);
checkSession(function () {
uploadFile(obj);
}, obj)
}
function setSession(s) {
session = s;
sessionIsFresh = true;
}
function mock(obj) {
var res = {
data: mockJson[obj.url] || mockJson[urlPerfix + obj.url]
};
if (successTrigger(res.data) && typeof obj.success === "function") {
// 接口返回成功码
obj.success(successData(res.data));
} else {
// 接口返回失败码
fail(obj, res);
}
if (typeof obj.complete === "function") {
obj.complete();
}
}
function getSession() {
return session;
}
function getConfig() {
return {
urlPerfix: urlPerfix,
sessionExpireTime: sessionExpireTime,
sessionExpireKey: sessionExpireKey,
sessionExpire: sessionExpire
}
}
module.exports = {
init: init,
request: requestWrapper,
uploadFile: uploadFileWrapper,
setSession: setSession,
login: login,
getSession: getSession,
getConfig: getConfig
};

View File

@@ -1,22 +1,34 @@
var path = require('path');
let path = require('path');
let webpack = require('webpack');
let pk = require('./package.json');
module.exports = [{
mode: 'production',
entry: './src/weRequest.js',
entry: './src/index.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'weRequest.min.js',
library: "weRequest",
libraryTarget: "commonjs-module"
},
plugins: [
new webpack.BannerPlugin({
banner: `weRequest ${pk.version}\n${pk.homepage}`
})
]
}, {
mode: 'development',
entry: './src/weRequest.js',
entry: './src/index.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'weRequest.js',
library: "weRequest",
libraryTarget: "commonjs-module"
},
devtool: 'inline-source-map'
devtool: 'inline-source-map',
plugins: [
new webpack.BannerPlugin({
banner: `weRequest ${pk.version}\n${pk.homepage}`
})
]
}]