feat(errorRetryBtn): 新增配置显示错误弹窗重试按钮 (#38)

feat: 新增配置显示错误弹窗重试按钮
This commit is contained in:
Cong Min
2020-03-09 19:38:57 +08:00
committed by GitHub
parent 0a361742b4
commit 9fd08ef19b
13 changed files with 107 additions and 44 deletions

View File

@@ -160,6 +160,7 @@ weRequest.request({
|errorTitle|String/Function|否|操作失败|接口逻辑失败时,错误弹窗的标题| |errorTitle|String/Function|否|操作失败|接口逻辑失败时,错误弹窗的标题|
|errorContent|String/Function|否||接口逻辑失败时,错误弹窗的内容| |errorContent|String/Function|否||接口逻辑失败时,错误弹窗的内容|
|errorCallback|Function|否||当出现接口逻辑错误时,会执行统一的回调函数,这里可以做统一的错误上报等处理| |errorCallback|Function|否||当出现接口逻辑错误时,会执行统一的回调函数,这里可以做统一的错误上报等处理|
|errorRetryBtn|Boolean|否|false|接口逻辑失败时,错误弹框是否显示重试按钮,点击重试可重新尝试发起请求|
|doNotCheckSession|Boolean|否|false|是否需要调用checkSession验证小程序的登录态过期若业务不需要使用到session_key则可配置为true| |doNotCheckSession|Boolean|否|false|是否需要调用checkSession验证小程序的登录态过期若业务不需要使用到session_key则可配置为true|
|reportCGI|Function|否||接口返回成功之后,会执行统一的回调函数,这里可以做统一的耗时上报等处理| |reportCGI|Function|否||接口返回成功之后,会执行统一的回调函数,这里可以做统一的耗时上报等处理|
|mockJson|Object|否||可为接口提供mock数据| |mockJson|Object|否||可为接口提供mock数据|
@@ -241,6 +242,8 @@ weRequest.init({
errorCallback: function(obj, res) { errorCallback: function(obj, res) {
// do some report // do some report
}, },
// [可选] 当出现错误时弹框是否显示重试按钮默认为false
errorRetryBtn: true,
// [可选] 是否需要调用checkSession验证小程序的登录态过期可不配置默认为false // [可选] 是否需要调用checkSession验证小程序的登录态过期可不配置默认为false
doNotCheckSession: true, doNotCheckSession: true,
// [可选] 上报耗时的函数name为上报名称startTime为接口调用开始时的时间戳endTime为接口返回时的时间戳 // [可选] 上报耗时的函数name为上报名称startTime为接口调用开始时的时间戳endTime为接口返回时的时间戳

View File

@@ -16,6 +16,7 @@ export interface IInitOption {
successData?: (res: string | IAnyObject | ArrayBuffer) => string | IAnyObject | ArrayBuffer; successData?: (res: string | IAnyObject | ArrayBuffer) => string | IAnyObject | ArrayBuffer;
errorTitle?: string | ((res: string | IAnyObject | ArrayBuffer) => string); errorTitle?: string | ((res: string | IAnyObject | ArrayBuffer) => string);
errorContent?: string | ((res: string | IAnyObject | ArrayBuffer) => string); errorContent?: string | ((res: string | IAnyObject | ArrayBuffer) => string);
errorRetryBtn?: boolean;
doNotUseQueryString?: boolean; doNotUseQueryString?: boolean;
} }
export interface ICodeToSessionOptions { export interface ICodeToSessionOptions {
@@ -43,6 +44,8 @@ export interface IRequestObject extends wx.RequestOption {
reLoginCount?: number; reLoginCount?: number;
_reportStartTime?: number; _reportStartTime?: number;
_reportEndTime?: number; _reportEndTime?: number;
_resolve?: (value?: any) => void;
_reject?: (reason?: any) => void;
} }
export interface IUploadFileOption extends IUploadFileObject { export interface IUploadFileOption extends IUploadFileObject {
beforeSend?: Function; beforeSend?: Function;
@@ -58,6 +61,8 @@ export interface IUploadFileObject extends wx.UploadFileOption {
reLoginCount?: number; reLoginCount?: number;
_reportStartTime?: number; _reportStartTime?: number;
_reportEndTime?: number; _reportEndTime?: number;
_resolve?: (value?: any) => void;
_reject?: (reason?: any) => void;
} }
export interface IGetConfigResult { export interface IGetConfigResult {
urlPerfix?: string | (() => string); urlPerfix?: string | (() => string);

View File

@@ -6,7 +6,7 @@ declare function getErrorMsg(res: wx.RequestSuccessCallbackResult | wx.UploadFil
title: string; title: string;
content: string; content: string;
}; };
declare function doError(title: string, content: string): void; declare function doError(title: string, content: string, retry?: () => any): void;
declare const _default: { declare const _default: {
systemError: typeof systemError; systemError: typeof systemError;
logicError: typeof logicError; logicError: typeof logicError;

View File

@@ -1,6 +1,7 @@
import { IRequestOption, IUploadFileOption } from "../interface";
declare function setSession(session: string): void; declare function setSession(session: string): void;
declare function delSession(): void; declare function delSession(): void;
declare function main(): Promise<unknown>; declare function main(relatedRequestObj?: IRequestOption | IUploadFileOption): Promise<unknown>;
declare const _default: { declare const _default: {
main: typeof main; main: typeof main;
setSession: typeof setSession; setSession: typeof setSession;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -56,6 +56,8 @@ weRequest.init({
errorCallback: function(obj, res) { errorCallback: function(obj, res) {
// do some report // do some report
}, },
// [可选] 当出现错误时弹框是否显示重试按钮默认为false
errorRetryBtn: true,
// [可选] 是否需要调用checkSession验证小程序的登录态过期可不配置默认为false // [可选] 是否需要调用checkSession验证小程序的登录态过期可不配置默认为false
doNotCheckSession: true, doNotCheckSession: true,
// [可选] 上报耗时的函数name为上报名称startTime为接口调用开始时的时间戳endTime为接口返回时的时间戳 // [可选] 上报耗时的函数name为上报名称startTime为接口调用开始时的时间戳endTime为接口返回时的时间戳

View File

@@ -1,6 +1,6 @@
{ {
"name": "we-request", "name": "we-request",
"version": "1.2.11", "version": "1.2.12",
"description": "本工具通过拓展小程序的wx.request让开发者通过简单的配置实现自动管理登录态等功能", "description": "本工具通过拓展小程序的wx.request让开发者通过简单的配置实现自动管理登录态等功能",
"keywords": [ "keywords": [
"登录态", "登录态",

View File

@@ -40,6 +40,8 @@ export interface IInitOption {
errorTitle?: string | ((res: string | IAnyObject | ArrayBuffer) => string); errorTitle?: string | ((res: string | IAnyObject | ArrayBuffer) => string);
/* 接口逻辑失败时,错误弹窗的内容 */ /* 接口逻辑失败时,错误弹窗的内容 */
errorContent?: string | ((res: string | IAnyObject | ArrayBuffer) => string); errorContent?: string | ((res: string | IAnyObject | ArrayBuffer) => string);
/* 接口逻辑失败时,错误弹窗是否显示重试按钮 */
errorRetryBtn?: boolean;
/* 当请求为非GET时不将登陆态等参数放在queryString上默认都放queryString */ /* 当请求为非GET时不将登陆态等参数放在queryString上默认都放queryString */
doNotUseQueryString?: boolean; doNotUseQueryString?: boolean;
} }
@@ -98,6 +100,10 @@ export interface IRequestObject extends wx.RequestOption{
_reportStartTime?: number; _reportStartTime?: number;
/* 请求返回的时间戳 */ /* 请求返回的时间戳 */
_reportEndTime?: number; _reportEndTime?: number;
/* 请求成功resolve */
_resolve?: (value?: any) => void;
/* 请求失败reject */
_reject?: (reason?: any) => void;
} }
export interface IUploadFileOption extends IUploadFileObject { export interface IUploadFileOption extends IUploadFileObject {
@@ -126,6 +132,10 @@ export interface IUploadFileObject extends wx.UploadFileOption {
_reportStartTime?: number; _reportStartTime?: number;
/* 请求返回的时间戳 */ /* 请求返回的时间戳 */
_reportEndTime?: number; _reportEndTime?: number;
/* 请求成功resolve */
_resolve?: (value?: any) => void;
/* 请求失败reject */
_reject?: (reason?: any) => void;
} }
export interface IGetConfigResult { export interface IGetConfigResult {

View File

@@ -1,11 +1,13 @@
import config from '../store/config' import config from '../store/config'
import request from '../api/request';
import { IRequestOption, IUploadFileOption } from "../interface"; import { IRequestOption, IUploadFileOption } from "../interface";
function systemError(obj: IRequestOption | IUploadFileOption, res: wx.GeneralCallbackResult) { function systemError(obj: IRequestOption | IUploadFileOption, res: wx.GeneralCallbackResult) {
if (typeof obj.fail === "function") { if (typeof obj.fail === "function") {
obj.fail(res); obj.fail(res);
} else { } else {
doError("", res.errMsg); const retry = () => request(obj).then(obj._resolve).catch(obj._reject);
doError("", res.errMsg, retry);
} }
} }
@@ -14,7 +16,8 @@ function logicError(obj: IRequestOption | IUploadFileOption, res: wx.RequestSucc
obj.fail(res); obj.fail(res);
} else { } else {
const {title, content} = getErrorMsg(res); const {title, content} = getErrorMsg(res);
doError(title, content); const retry = () => request(obj).then(obj._resolve).catch(obj._reject);
doError(title, content, retry);
} }
// 如果有配置统一错误回调函数,则执行它 // 如果有配置统一错误回调函数,则执行它
@@ -49,12 +52,21 @@ function getErrorMsg(res: wx.RequestSuccessCallbackResult | wx.UploadFileSuccess
return {title, content} return {title, content}
} }
function doError(title: string, content: string) { function doError(title: string, content: string, retry?: () => any) {
wx.showModal({ // 是否显示重试按钮
const showErrorRetryBtn = config.errorRetryBtn && typeof retry === "function";
wx.showModal(Object.assign({
title, title,
content: content || "网络或服务异常,请稍后重试", content: content || "网络或服务异常,请稍后重试",
}, !showErrorRetryBtn ? {
showCancel: false showCancel: false
}) } : {
showCancel: true,
confirmText: '重试',
success(res: wx.ShowModalSuccessCallbackResult) {
if (res.confirm && typeof retry === "function") retry();
}
}));
} }
export default { export default {

View File

@@ -25,7 +25,7 @@ function format(originUrl: string) {
} }
// 所有请求发出前需要做的事情 // 所有请求发出前需要做的事情
function preDo<T extends IRequestOption | IUploadFileOption>(obj: T): T { function preDo<T extends IRequestOption | IUploadFileOption>(obj: T, resolve: (value?: any) => void, reject?: (reason?: any) => void): T {
if (typeof obj.beforeSend === "function") { if (typeof obj.beforeSend === "function") {
obj.beforeSend(); obj.beforeSend();
} }
@@ -45,6 +45,9 @@ function preDo<T extends IRequestOption | IUploadFileOption>(obj: T): T {
obj.url = format(obj.url); obj.url = format(obj.url);
} }
obj._resolve = resolve;
obj._reject = reject;
return obj; return obj;
} }
@@ -174,7 +177,7 @@ function doUploadFile(obj: IUploadFileOption) {
function request(obj: IRequestOption): any { function request(obj: IRequestOption): any {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
obj = preDo(obj); obj = preDo(obj, resolve, reject);
if (config.mockJson) { if (config.mockJson) {
let mockResponse = mockManager.get(obj); let mockResponse = mockManager.get(obj);
@@ -188,7 +191,7 @@ function request(obj: IRequestOption): any {
cacheManager.get(obj); cacheManager.get(obj);
} }
sessionManager.main().then(() => { sessionManager.main(obj).then(() => {
return doRequest(obj) return doRequest(obj)
}).then((res) => { }).then((res) => {
let response = responseHandler(res as wx.RequestSuccessCallbackResult, obj, 'request'); let response = responseHandler(res as wx.RequestSuccessCallbackResult, obj, 'request');
@@ -203,7 +206,7 @@ function request(obj: IRequestOption): any {
function uploadFile(obj: IUploadFileOption): any { function uploadFile(obj: IUploadFileOption): any {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
obj = preDo(obj); obj = preDo(obj, resolve, reject);
if (config.mockJson) { if (config.mockJson) {
let mockResponse = mockManager.get(obj); let mockResponse = mockManager.get(obj);
@@ -213,7 +216,7 @@ function uploadFile(obj: IUploadFileOption): any {
} }
} }
sessionManager.main().then(() => { sessionManager.main(obj).then(() => {
return doUploadFile(obj) return doUploadFile(obj)
}).then((res) => { }).then((res) => {
let response = responseHandler(res as wx.UploadFileSuccessCallbackResult, obj, 'uploadFile'); let response = responseHandler(res as wx.UploadFileSuccessCallbackResult, obj, 'uploadFile');

View File

@@ -4,6 +4,8 @@ import errorHandler from './errorHandler'
import durationReporter from './durationReporter' import durationReporter from './durationReporter'
import requestHandler from './requestHandler' import requestHandler from './requestHandler'
import loading from '../util/loading' import loading from '../util/loading'
import request from '../api/request'
import { IRequestOption, IUploadFileOption } from "../interface";
/* 生命周期内只做一次的checkSession */ /* 生命周期内只做一次的checkSession */
let checkSessionPromise: any = null; let checkSessionPromise: any = null;
@@ -209,17 +211,22 @@ function delSession() {
} }
} }
function main() { function main(relatedRequestObj?: IRequestOption | IUploadFileOption) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let retry = !relatedRequestObj
// 如果没有关联的请求,重试即调用自身
? () => main().then(resolve).catch(reject)
// 如果有关联的请求,重试即调用所关联的请求
: () => request(relatedRequestObj).then(relatedRequestObj._resolve).catch(relatedRequestObj._reject);
return checkLogin().then(() => { return checkLogin().then(() => {
return config.doNotCheckSession ? Promise.resolve() : checkSession() return config.doNotCheckSession ? Promise.resolve() : checkSession()
}, ({title, content}) => { }, ({title, content}) => {
errorHandler.doError(title, content); errorHandler.doError(title, content, retry);
return reject({title, content}); return reject({title, content});
}).then(() => { }).then(() => {
return resolve(); return resolve();
}, ({title, content})=> { }, ({title, content})=> {
errorHandler.doError(title, content); errorHandler.doError(title, content, retry);
return reject({title, content}); return reject({title, content});
}) })
}) })

View File

@@ -18,6 +18,7 @@ const defaultConfig: IInitOption = {
errorContent(res: any) { errorContent(res: any) {
return res return res
}, },
errorRetryBtn: false,
reLoginLimit: 3, reLoginLimit: 3,
errorCallback: null, errorCallback: null,
reportCGI: false, reportCGI: false,