当我们通过uni.addInterceptor(method, interceptor)
添加api拦截器时,会依次调用
defineSyncApi("addInterceptor", callback, protocol, undefine)(method, interceptor)
wrapperSyncApi("addInterceptor", callback, protocol, undefine)(method, interceptor)
wrapperSyncApi("addInterceptor", callback, protocol, undefine)(method, interceptor)
的调用过程如下
function wrapperSyncApi(name, fn, protocol, options) {
return (...args) => {
//name = "addIntercept"
//fn = callback
//protocol = protocol
//options = undefine
//args = [method, intercepter]
const errMsg = beforeInvokeApi(name, args, protocol, options);
if (errMsg) {
throw new Error(errMsg);
}
return fn.apply(null, args);
};
}
因此,接下来会调用beforeInvokeApi("addInterceptor", [method, interceptor], protocol, options)
,beforeInvokeApi的代码很繁琐,但是只干了一件事,就是校验我们调用uni.addInterceptor(method, interceptor)
时传入的method和interceptor参数是否合法,如果参数不合法,系统会抛出一个异常,ApiInterceptor添加失败,如果参数合法,则会调用fn.apply(null, args),也就会调用到callback,uni.addInterceptor
的核心就是在callback中完成的。
const callback = (method, interceptor) => {
if (isString(method) && isPlainObject(interceptor)) {
mergeInterceptorHook(scopedInterceptors[method] || (scopedInterceptors[method] = {}), interceptor);
} else if (isPlainObject(method)) {
mergeInterceptorHook(globalInterceptors, method);
}
}
当我们调用uni.addInterceptor
时,如果传入了method, interceptor
,则会把interceptor的信息记录在scopedInterceptors中;如果只传入了interceptor
,则会把interceptor的信息记录在globalInterceptors中。
紧接着调用mergeInterceptorHook(rawInterceptors, interceptor)
,mergeInterceptorHook的调用流程如下图:
当我们调用uni.addInterceptor(method, interceptor)
添加拦截器时,会按照调用顺序依次把要添加的interceptor的各个属性合并到uni-app内置的一个常量对象scopedInterceptors中,如果说scopedInterceptors中已经包含了要添加的interceptor的属性,那么则不会被重复添加,注: 这里指的包含是指同一个function,而不是指相同实现的不同function
uni.addInterceptor("showLoading", {
invoke: function(args) {},
success: function(args) {},
fail: function(err) {},
complete: function(res) {},
returnValue: function(args) {}
})
uni.addInterceptor("showLoading", {
invoke: function(args) {},
success: function(args) {},
fail: function(err) {},
complete: function(res) {},
returnValue: function(args) {}
})
scopedInterceptors = {
"showLoading": {
"invoke": [function(args) { console.log("invoke1", "invoke1") }, function(args) { console.log("invoke2", "invoke2") }],
"success": [function(args) { console.log("success1", "success1") }, function(args) { console.log("success2", "success2") }],
"fail": [function(err) { console.log("fail1", "fail1") }, function(err) { console.log("fail2", "fail2") }],
"complete": [function(res) { console.log("complete1", "complete1") }, function(res) { console.log("complete2", "complete2") }],
"returnValue": [function(args) { return args }, function(args) { return undefine }]
}
}
const invoke = function(args) {}
const success = function(args) {}
const fail = function(args) {}
const complete = function(args) {}
const returnValue = function(args) {}
uni.addInterceptor("showLoading", {
invoke,
success,
fail,
complete,
returnValue
})
uni.addInterceptor("showLoading", {
invoke,
success,
fail,
complete,
returnValue
})
scopedInterceptors = {
"showLoading": {
"invoke": [function(args) {}],
"success": [function(args) {}],
"fail": [function(args) {}],
"complete": [function(args) {}],
"returnValue": [function(args) {}]
}
}
和addInterceptor
的流程类似,uni.removeInterceptor
的核心也是在callback中完成的:
const removeInterceptor = defineSyncApi(API_REMOVE_INTERCEPTOR, (method, interceptor) => {
if (isString(method)) {
if (isPlainObject(interceptor)) {
removeInterceptorHook(scopedInterceptors[method], interceptor);
} else {
delete scopedInterceptors[method];
}
} else if (isPlainObject(method)) {
removeInterceptorHook(globalInterceptors, method);
}
}, RemoveInterceptorProtocol);
紧接着调用removeInterceptorHook(rawInterceptors, interceptor)
,removeInterceptorHook的调用流程如下图:
const invoke = function(args) {
args.title = "加载中"
args.mask = true
return true
}
uni.addInterceptor("showLoading", {
invoke: invoke
})
uni.removeInterceptor("showLoading", {
invoke: invoke
})