智能照明系统APP-本地串口
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.
LightingSystemApp-serial/.svn/pristine/3c/3ce0a2b1b8321eb06b851b5d4a9...

326 lines
7.6 KiB

3 years ago
import {
isFn,
isPlainObject
} from 'uni-shared'
import {
tryCatch,
tryCatchFramework
} from './catch'
import {
isTaskApi,
isSyncApi,
isCallbackApi
} from './promise'
import protocol from 'uni-api-protocol'
import validateParam from './params'
function invokeCallbackHandlerFail (err, apiName, callbackId) {
const errMsg = `${apiName}:fail ${err}`
if (process.env.NODE_ENV !== 'production') {
console.error(errMsg)
}
if (callbackId === -1) {
throw new Error(errMsg)
}
if (typeof callbackId === 'number') {
invokeCallbackHandler(callbackId, {
errMsg
})
}
return false
}
const callbackApiParamTypes = [{
name: 'callback',
type: Function,
required: true
}]
// 目前已用到的仅这三个
// 完整的可能包含:
// beforeValidate,
// beforeSuccess,
// afterSuccess,
// beforeFail,
// afterFail,
// beforeCancel,
// afterCancel,
// beforeAll,
// afterAll
const IGNORE_KEYS = [
'beforeValidate',
'beforeAll',
'beforeSuccess'
]
function validateParams (apiName, paramsData, callbackId) {
let paramTypes = protocol[apiName]
if (!paramTypes && isCallbackApi(apiName)) {
paramTypes = callbackApiParamTypes
}
if (paramTypes) {
if (Array.isArray(paramTypes) && Array.isArray(paramsData)) {
const paramTypeObj = Object.create(null)
const paramsDataObj = Object.create(null)
const paramsDataLength = paramsData.length
paramTypes.forEach((paramType, index) => {
paramTypeObj[paramType.name] = paramType
if (paramsDataLength > index) {
paramsDataObj[paramType.name] = paramsData[index]
}
})
paramTypes = paramTypeObj
paramsData = paramsDataObj
}
if (isFn(paramTypes.beforeValidate)) {
const err = paramTypes.beforeValidate(paramsData)
if (err) {
return invokeCallbackHandlerFail(err, apiName, callbackId)
}
}
const keys = Object.keys(paramTypes)
for (let i = 0; i < keys.length; i++) {
if (IGNORE_KEYS.indexOf(keys[i]) !== -1) {
continue
}
const err = validateParam(keys[i], paramTypes, paramsData)
if (err) {
return invokeCallbackHandlerFail(err, apiName, callbackId)
}
}
}
return true
}
let invokeCallbackId = 1
const invokeCallbacks = {}
function createKeepAliveApiCallback (apiName, callback) {
const callbackId = invokeCallbackId++
const invokeCallbackName = 'api.' + apiName + '.' + callbackId
const invokeCallback = function (res, extras) {
callback(res, extras)
}
invokeCallbacks[callbackId] = {
name: invokeCallbackName,
keepAlive: true,
callback: invokeCallback
}
return callbackId
}
function createApiCallback (apiName, params = {}, extras = {}) {
if (!isPlainObject(params)) {
return {
params
}
}
params = Object.assign({}, params)
const apiCallbacks = {}
for (const name in params) {
const param = params[name]
if (isFn(param)) {
apiCallbacks[name] = tryCatch(param)
delete params[name]
}
}
const {
success,
fail,
cancel,
complete
} = apiCallbacks
const hasSuccess = isFn(success)
const hasFail = isFn(fail)
const hasCancel = isFn(cancel)
const hasComplete = isFn(complete)
if (!hasSuccess && !hasFail && !hasCancel && !hasComplete) { // 无回调
return {
params
}
}
const wrapperCallbacks = {}
for (const name in extras) {
const extra = extras[name]
if (isFn(extra)) {
wrapperCallbacks[name] = tryCatchFramework(extra)
}
}
const {
beforeSuccess,
afterSuccess,
beforeFail,
afterFail,
beforeCancel,
afterCancel,
beforeAll,
afterAll
} = wrapperCallbacks
const callbackId = invokeCallbackId++
const invokeCallbackName = 'api.' + apiName + '.' + callbackId
const invokeCallback = function (res) {
res.errMsg = res.errMsg || apiName + ':ok'
// 部分 api 可能返回的 errMsg 的 api 名称部分不一致,格式化为正确的
if (res.errMsg.indexOf(':ok') !== -1) {
res.errMsg = apiName + ':ok'
} else if (res.errMsg.indexOf(':cancel') !== -1) {
res.errMsg = apiName + ':cancel'
} else if (res.errMsg.indexOf(':fail') !== -1) {
let errDetail = ''
const spaceIndex = res.errMsg.indexOf(' ')
if (spaceIndex > -1) {
errDetail = res.errMsg.substr(spaceIndex)
}
res.errMsg = apiName + ':fail' + errDetail
}
isFn(beforeAll) && beforeAll(res)
const errMsg = res.errMsg
if (errMsg.indexOf(apiName + ':ok') === 0) {
isFn(beforeSuccess) && beforeSuccess(res)
hasSuccess && success(res)
isFn(afterSuccess) && afterSuccess(res)
} else if (errMsg.indexOf(apiName + ':cancel') === 0) {
res.errMsg = res.errMsg.replace(apiName + ':cancel', apiName + ':fail cancel')
hasFail && fail(res)
isFn(beforeCancel) && beforeCancel(res)
hasCancel && cancel(res)
isFn(afterCancel) && afterCancel(res)
} else if (errMsg.indexOf(apiName + ':fail') === 0) {
isFn(beforeFail) && beforeFail(res)
hasFail && fail(res)
isFn(afterFail) && afterFail(res)
}
hasComplete && complete(res)
isFn(afterAll) && afterAll(res)
}
invokeCallbacks[callbackId] = {
name: invokeCallbackName,
callback: invokeCallback
}
return {
params,
callbackId
}
}
function createInvokeCallback (apiName, params = {}, extras = {}) {
const {
params: args,
callbackId
} = createApiCallback(apiName, params, extras)
if (isPlainObject(args) && !validateParams(apiName, args, callbackId)) {
return {
params: args,
callbackId: false
}
}
return {
params: args,
callbackId
}
}
// onNativeEventReceive((event,data)=>{}) 需要两个参数,写死最多两个参数,避免改动太大,影响已有逻辑
export function invokeCallbackHandler (invokeCallbackId, res, extras) {
if (typeof invokeCallbackId === 'number') {
const invokeCallback = invokeCallbacks[invokeCallbackId]
if (invokeCallback) {
if (!invokeCallback.keepAlive) {
delete invokeCallbacks[invokeCallbackId]
}
return invokeCallback.callback(res, extras)
}
}
return res
}
export function wrapperUnimplemented (name) {
return function todo (args) {
console.error('API `' + name + '` is not yet implemented')
}
}
function wrapperExtras (name, extras) {
const protocolOptions = protocol[name]
if (protocolOptions) {
isFn(protocolOptions.beforeAll) && (extras.beforeAll = protocolOptions.beforeAll)
isFn(protocolOptions.beforeSuccess) && (extras.beforeSuccess = protocolOptions.beforeSuccess)
}
}
export function wrapper (name, invokeMethod, extras = {}) {
if (!isFn(invokeMethod)) {
return invokeMethod
}
wrapperExtras(name, extras)
return function (...args) {
if (isSyncApi(name)) {
if (validateParams(name, args, -1)) {
return invokeMethod.apply(null, args)
}
} else if (isCallbackApi(name)) {
if (validateParams(name, args, -1)) {
return invokeMethod(createKeepAliveApiCallback(name, args[0]))
}
} else {
let argsObj = {}
if (args.length) {
argsObj = args[0]
}
const {
params,
callbackId
} = createInvokeCallback(name, argsObj, extras)
if (callbackId !== false) {
let res
if (isFn(params)) {
res = invokeMethod(callbackId)
} else {
res = invokeMethod(params, callbackId)
}
if (res && !isTaskApi(name)) {
res = invokeCallbackHandler(callbackId, res)
if (isPlainObject(res)) {
res.errMsg = res.errMsg || name + ':ok'
}
}
return res
}
}
}
}