扩展 API 介绍 若当前开源的 API 不能满足宿主需求,宿主可扩展其私有 API。
宿主可扩展的私有 API 分为两类,一类是百度 APP 私有 API,另一类是宿主私有 API。
接下来,首先介绍 API 分类,然后介绍宿主扩展 API 的方式,最后给出不同类型的 API 扩展方式的详述。
API 分类
调用端能力的 API
无前端参数特殊处理
开发者调用 API 时,传入的参数通过底层 js-native 的 argCheck 进行校验即可满足需求,不需要对开发者传入的参数进行校验或者过滤,这种情况属于无前端参数特殊处理的情况。其中,argCheck 依赖于描述表 中的 args 参数。下面的描述表部分将有args
参数的详述。
有前端参数特殊处理
如果开发者入参中存在 js-native 不能判断的类型或者客户端无法识别的类型,如 ArrayBuffer,那么需要前端做类型判断,并将 ArrayBuffer 转换成 js-native 能够判断或者客户端可以识别的类型后再进行端能力的调起。
有复杂上下文逻辑
在调起端能力之前,除了需要对开发者参数进行特殊校验和处理外,还需要其它前端逻辑的处理,这种情况属于有复杂上下文逻辑的情况。
不调用端能力的 API
宿主扩展 API 的方式 宿主扩展 API 有两个不可或缺的部分,一个是描述表,另一个是 API 的调起方法。
描述表 描述表 是一份端能力的描述,里面描述了一些前端和客户端的通信方式、参数等,所以一定要正确书写描述表,否则端能力是无法生效的。
描述表撰写方法 了解 js-native 描述表的各个参数的含义,然后手动撰写。 单个端能力的描述表举例,此时假设宿主的名字为 hostA:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { name : 'hostA.test' , authority : 'swanAPI' , path : '/test' , args : [ { name : 'key' , value : 'string=' }, { name : 'content' , value : 'string' } ], invoke : 'swan.method.json' , method : '_naSwan._naTest.test' , extension : 'swan' }
具体的参数说明如下:
参数
类型
含义
备注
name
string
端能力的名称,如 ‘hostA.test’
请注意 API 命名规范 ,需要以 ${hostName}.${apiName} 的形式进行命名, 其中 hostName 为定义在 swan 下的宿主命名空间, 需要与通过客户端提供的全局方法 getEnvVariables 获取的 hostName 字段保持一致,否则将影响 API 的挂载。
authority
string
调用端能力 scheme 中对应的 authority
可以参看 URI 的 authority 定义
path
string
调用端能力 scheme 中对应的 path
可以参看 URI 的 path 定义
args
Array.<object>
调用端能力时需要的参数
下边此参数的介绍和举例,更详细的内容请参考值类型系统
invoke
string
调用过程的处理
有效值见下表
method
string
调用端能力实际调起的客户端方法
只有 iOS 端 jsc 环境下的 API 以及 Android 的 API 需要此字段
handler
string
JS 使用 postMessage 向客户端发送信息时的 message name
iOS 端独有,只有 webveiw 环境下的异步 API 才需要此字段
extension
string
表示该端能力为私有的,可选值为'swan'
和 'boxjs'
'swan'
表示将该 API 挂载在swan.${hostName}
下供开发者调用,'boxjs'
表示将该 API 挂载在 boxjs 上供宿主内部小程序框架调用,一般是不想对开发者开放的端能力,比如扩展组件中调用的端能力。
invoke
有效值如下:
有效值
含义
'swan.message.url'
scheme 方式调用,iOS端 webview 环境异步 API
'swan.prompt'
scheme 方式调用,iOS 端 webview 环境同步 API
'swan.method.url'
scheme 方式调用,Android 端 webview/v8 环境下的的同/异步 API,iOS 端 jsc 环境的异步 API
'swan.method.json'
binding 方式调用,iOS 端 jsc 环境下的同/异步 API
'swan.method.jsonString'
binding 方式调用,Android 端 webview/v8 环境下同/异步 API
args
参数说明:args
参数与参数校验有关,当前参数校验支持 boolean
、string
、number
、function
、Object
、Array
和 *
这几种类型,args
参数定义的举例如下:
参数key
应为string
类型且为必传,data
参数为Object
类型且为非必传:1 2 3 4 5 6 7 8 9 10 'args' : [ { 'name' : 'key' , 'value' : 'string' }, { 'name' : 'data' , 'value' : 'Object=' } ]
参数key
必须为a
、b
和c
中的一个且为必传,使用oneOf
属性:1 2 3 4 5 6 7 8 9 10 11 12 13 14 'args' : [ { 'name' : 'key' , 'value' : { 'oneOf' : [ 'a' , 'b' , 'c' ], 'isRequired' : true } } ]
参数data
必须为string
或Array
类型且非必传,使用oneofType
属性:1 2 3 4 5 6 7 8 9 'args' : [ { 'name' : 'data' , 'value' : { 'oneofType' : ['string' , 'Array' ], 'isRequired' : false } } ]
参数data
必须为数组且数组中的每一项都是string
类型且为必传,使用arrayOf
属性:1 2 3 4 5 6 7 8 9 'args' : [ { 'name' : 'data' , 'value' : { 'arrayOf' : 'string' , 'isRequired' : true } } ]
描述表维护位置 描述表维护在客户端或前端 extension 模块中,推荐将描述表维护在客户端,客户端描述表详情请参阅 iOS 接入指南 和 Android 接入指南 。描述表举例如下,此时假设宿主的名字为 hostA:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 [ { name : 'hostA.add' , authority : 'swanAPI' , path : '/add' , args : [ { name : 'id' , value : 'number' }, { name : 'detail' , value : 'string' } ], invoke : 'swan.method.json' , method : '_naSwan._naAdd.add' , extension : 'swan' }, { name : 'hostA.delete' , authority : 'swanAPI' , path : '/delete' , args : [ { name : 'id' , value : 'number' } ], invoke : 'swan.method.json' , method : '_naSwan._naDelete.delete' , extension : 'swan' }, ... ]
前端调起方法挂载配置 在智能小程序运行时,会将描述表添加到 jsNative 的 container 中,并将每个端能力的调起方法挂载在 boxjs 上,前端通过boxjs[${name}]
即可调起其对应的端能力。
在 extension 包 中提到过前端的 swan-extension 模块(后统称为 extension 模块)的定义,其中一个字段是 methods,它表示前端 extension 模块所维护的挂载 API 的调起方法时使用的配置集合,类型为 Object,这个对象中,key 为要挂载到宿主命名空间下的 API 名称,value 为挂载该 API 调起方法时所使用的配置,这个配置包含以下几项:
method:挂载的方法,即调用 API 时调用的方法。
scope:此属性将决定 method 挂载的命名空间。如果此值为'root'
,小程序运行时会将 method 挂载在 swan 下,即开发者通过swan.${apiName}
来调用;未定义 scope 时,挂载在宿主命名空间下,即开发者通过swan.${hostName}.${apiName}
来调用。需要注意,只有当前命名空间下不存在此 API 时,才能挂载成功。
methods 定义的举例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let methods = { add : { scope : 'root' , method : () => { console .log ('hostA.add API' ); } }, delete : { method : () => { console .log ('hostA.delete API' ); } }, ... };
扩展方式 不管是扩展百度 APP 私有的 API 还是扩展宿主私有的 API,主要有以下四种扩展方式: 方式一:客户端维护描述表并实现相应的端能力。这种方式下,智能小程序运行时除了会将描述表添加到 container 中,还会依据描述表进行调起方法的挂载。详见下边的扩展方式详述部分。 方式二:客户端维护描述表并实现相应的端能力,extension 模块实现要挂载的调起方法。这种方式下,小程序框架运行时会将描述表添加到 container 中,并根据 swan-extension 模块进行调起方法的挂载。详见下边的扩展方式详述部分。 方式三:extension 模块维护描述表并实现要挂载 API 的调起方法。详见下边的扩展方式详述部分。 方式四:extension 模块实现要挂载的调起方法。详见下边的扩展方式详述部分。
对于各个类别的 API,可使用下图标注的方式进行扩展。
扩展方式详述 方式一:客户端维护描述表并实现相应的端能力 此方式是指前端无需维护 extension 模块,仅宿主客户端维护 API 的端能力描述表并实现相应的端能力即可完成扩展。
原理 智能小程序运行时将宿主客户端维护的描述表注入到 js-native 的 container 中,并通过描述表中每个端能力的 name(形如${hostName}.${apiName}
),将 API 的调起方法挂载到 swan.${hostName} 的命名空间下,此处的调起方法指智能小程序框架实现的通用的调起端能力的方法。
使用方式 开源宿主客户端在实现私有端能力的基础上,按照上述描述表撰写方法中的规则维护描述表,此时描述表中的 extension 字段建议定义为 ‘swan’。
以宿主 hostA 新增 API addBook 为例,宿主客户端需要维护如下所示的描述表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [{ name : 'hostA.addBook' , authority : 'swanAPI' , path : '/addBook' , args : [ { name : 'bookName' , value : 'string=' }, { name : 'bookId' , value : 'string' } ], invoke : 'swan.method.json' , method : '_naSwan._naBook.addBook' , extension : 'swan' }]
方式二:客户端维护描述表并实现相应的端能力 + extension 模块实现要挂载的方法 此方式是指宿主客户端维护描述表,而要挂载到宿主名命名空间的方法由前端 extension 模块实现。
原理 智能小程序运行时将描述表注入到 js-native 的 container 中;在 extension 模块进行 API 调起方法的实现,当智能小程序运行时加载 extension 模块时,会将模块导出的调起方法挂载到模块定义的 name 的命名空间下,即挂载到 swan.${name} 上。
使用方式 1. 针对开发者入参进行特殊处理的 API 客户端进行描述表的维护以及相应端能力的实现,描述表的维护方式可参见上述描述表部分,此时描述表中的 extension 字段建议定义为 ‘boxjs’;挂载的方法由 extension 模块来实现,接下来通过举例的方式进行介绍。 假设此时的宿主为 hostA,若要开发一个有入参特殊处理的 API testDemo,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 export const testDemo = boxjs => params => { let apiName = 'testDemo' ; if (param.value ) { let type = Object .prototype .toString .call (params.timeout ).slice (8 , -1 ); if (type !== 'ArrayBuffer' ) { callFailAndComplete (params, apiName, `parameter error: value should be ArrayBuffer instead of ${type} ` ) } } params.value = arrayBufferToBase64 (params.value ); let invokePromise = boxjs[`hostA.${apiName} ` ](params); executeCallback ({ promise, apiName }, params); };
此时 extension 模块的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 import {testDemo} from './testDemo' ;define ('swan-extension' , ['swan' , 'boxjs' ], function (require , module , exports , define, swan, boxjs ) { module .exports = { name : 'hostA' , methods : { testDemo : { method : testDemo (boxjs) } } }; });
通用函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 function executeByTryCatch (fn, errMsg, params ) { try { fn && fn (params); } catch (err) { console .error (`thirdScriptError\n${err.message} ; ${errMsg} \n${err.stack} ` ); } } function callFailAndComplete (params, apiName, errMsg, errCode = 904 ) { errMsg = `${apiName} :fail ${errMsg} ` ; if (Object .prototype .toString .call (params).slice (8 , -1 ) === 'Object' ) { executeByTryCatch (params.fail , 'at api ' + apiName + ' fail callback function' , {errCode, errMsg}); executeByTryCatch (params.complete , 'at api ' + apiName + ' complete callback function' , {errCode, errMsg}); } }; function executeCallback (options, params = {} ) { let {promise, apiName} = options; if (promise instanceof Array ) { Promise .all (promise) .then (function ([callbackRes, cbRes] ) { executeDeveloperCallback (apiName, cbRes, 'success' , params); }).catch (err => { const result = err instanceof Error ? {errCode : 904 , errMsg : err.message } : err; executeDeveloperCallback (apiName, result, 'fail' , params); }); } else { promise.then (res => { executeDeveloperCallback (apiName, res, 'success' , params); }).catch (err => { const result = err instanceof Error ? {errCode : 904 , errMsg : err.message } : err; executeDeveloperCallback (apiName, result, 'fail' , params); }); } }; function executeDeveloperCallback (apiName, res, callbackName, params ) { const ERROR_PREFIX = 'at api' ; const ERROR_SUFFIX = 'callback function' ; const ERROR_MSG = { success : `${ERROR_PREFIX} ${apiName} success ${ERROR_SUFFIX} ` , fail : `${ERROR_PREFIX} ${apiName} fail ${ERROR_SUFFIX} ` , complete : `${ERROR_PREFIX} ${apiName} complete ${ERROR_SUFFIX} ` }; executeByTryCatch (params[callbackName], ERROR_MSG [callbackName], res); executeByTryCatch (params.complete , ERROR_MSG .complete , res); }
2. 有复杂上下文逻辑的 API 客户端维护描述表并实现相应的端能力,描述表的维护方式可参见上述描述表部分;挂载的方法由 extension 模块来实现,接下来通过举例的方式进行介绍。 假设宿主 hostA 想要新增一个有上下文依赖的的 API createTestContext,那么需要前端进行开发处理逻辑,最终通过 boxjs[${端能力名称}] 来调用端能力,需要注意的是 boxjs 调用端能力返回值为一个 Promise,开发者的回调函数需要在 Promise 的链式处理进行自定义逻辑处理,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 export const initTestContext = boxjs => params => { class TestContext { open (params = {} ) { boxjs['hostA.openTest' ](params) .then (res => { }) .catch (err => { }); } } return () => new TestContext () };
extension 模块的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import {initTestContext} from './createTestContext' ;define ('swan-extension' , ['swan' , 'boxjs' ], function (require , module , exports , define, swan, boxjs ) { module .exports = { name : `hostA` , methods : { createTestContext : { method : initTestContext (swan) } } components : {}, customLog (swanEventFlow ) {}, getCanIUseMap : () => {} }; });
方式三:extension 模块维护描述表并实现要挂载的方法 + 客户端实现相应的端能力 此方式是指 extension 模块维护描述表并实现要挂载的方法,客户端实现相应的端能力。
原理 智能小程序运行时加载 extension 模块,将 extension 模块中维护的描述表注入到 boxjs 的 container 中;根据 extension 模块定义的 name,将 API 对应的方法挂载到 swan.${name} 的命名空间下。
使用方式 前端维护描述表的方式可参照描述表撰写方法中介绍的方式进行维护;API 的挂载方法的实现可参照方式二中介绍的方式进行实现,此处需要注意的是,由于前端维护的描述表会被注入到 boxjs 的 container 中,所以此时需要通过 boxjs 进行端能力的调起。我们还是以方式二中提到的 testDemo API 为例,介绍这种方式下具体该如何扩展。
此时描述表如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export const hostMethodDescriptions = [ { name : 'hostA.testDemo' , authority : 'swanAPI' , path : '/testDemo' , args : [ { name : 'value' , value : 'string=' } ], invoke : 'swan.method.json' , method : '_naSwan._naTestDemo.testDemo' } ];
此时 method 以及 extension 模块的定义与方式二中的相同。
方式四:extension 模块实现要挂载的方法 此方式适用于不需要调用端能力的 API,所以不需要维护描述表且不需要客户端实现端能力,只通过前端逻辑即可实现。下面将介绍纯前端 API 的例子和监听类 API 的例子。
纯前端 API 举例 假设我们要提供给开发者 add API,此 API 的作用是对传入的两个数字进行相加并返回结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 export const add = (a, b ) => { if (!Number .isFinite (a) || !Number .isFinite (b)) { throw new Error ('hostA.add API: parameter error: param a and param b should be typeof Number' ); } return a + b; };
extension 模块的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import {add} from './add' ;define ('swan-extension' , ['swan' , 'boxjs' ], function (require , module , exports , define, swan, boxjs ) { module .exports = { name : 'hostA' , methods : { add : { method : add } } components : {}, customLog (swanEventFlow ) {}, getCanIUseMap : () => {} }; });
监听类 API 举例 假设我们要提供给开发者一个对客户端 test 事件的监听,此时需要定义 onTest API 用于启用监听,offTest API 用于取消监听。
1. 增加监听 onTest 通过通用的 eventsListenerAdder 方法添加监听,用于监听客户端派发的事件,此方法接收1个参数对象,对象中共有5个参数,如下:
参数名
类型
必填
含义
listenerName
string
是
客户端派发的事件名称,当前我们举例的 API 的名字为 onTest,那么这个事件名称需要约定为 test
callback
Function
是
开发者传入的回调函数
methodName
string
否
当前监听类 API 的名字,即 onTest
context
Object
否
调用的上下文
parser
Function
否
对客户端派发事件里的 data 数据的解析函数
eventsListenerAdder 方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 const EventAction = { ON : 'on' , OFF : 'off' , HAS : 'has' }; let eventAddedFlags = {};const eventEmitter = new EventEmitter ();const composeEventName = (listenerName, action ) => action + listenerName[0 ].toUpperCase () + listenerName.slice (1 );export const eventsListenerAdder = options => { let { listenerName, callback, methodName, context, parser } = options; let eventFlag = composeEventName (listenerName, EventAction .HAS ); if (!eventAddedFlags[eventFlag]) { global .addEventListener (listenerName, res => { eventEmitter.handlerQueueSet .get (listenerName) .queue .forEach (item => { item.handler .call (context, parser (res.data )); }); }); eventAddedFlags[eventFlag] = true ; } if (typeof callback === 'function' ) { eventEmitter.on (listenerName, callback); } else { let methodTipName = methodName || composeEventName (listenerName, EventAction .ON ); console .error ( `${methodTipName} Parameter Error: ${methodTipName} accepts a function instead of ${typeof callback} ` ); } };
2. 取消监听 通过通用的 eventsListenerRemover 方法添加监听,用于监听客户端派发的事件,此方法接收1个参数对象,对象中共有3个参数:
参数名
类型
必填
含义
listenerName
string
是
要取消监听的事件名称,当前我们举例的 API 的名字为 onTest,那么这个事件名称为 test
callback
Function
否
如果不填写此参数,将取消 listenerName 事件的所有监听;如果填写此参数,则将此回调函数从事件队列中移除,若事件队列中没有匹配的回调函数,则不移除任何回调函数,若有多个匹配,则只移除队尾的回调函数
methodName
string
否
当前取消监听 API 的名字,即 offTest
eventsListenerRemover 方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 const EventAction = { ON : 'on' , OFF : 'off' , HAS : 'has' }; let eventAddedFlags = {}; const eventEmitter = new EventEmitter (); const composeEventName = (listenerName, action ) => action + listenerName[0 ].toUpperCase () + listenerName.slice (1 ); export const eventsListenerRemover = options => { let { listenerName, callback, methodName } = options; if (callback && typeof callback !== 'function' ) { let methodTipName = methodName || composeEventName (listenerName, EventAction .ON ); console .error ( `${methodTipName} Parameter Error: ${methodTipName} accepts a function instead of ${typeof callback} ` ); return ; } eventEmitter.removeListener (listenerName, callback); };
接下来,使用上述的通用函数,为宿主 hostA 增加监听类 API onTest 和 offTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 export function eventDataParser (data ) { let result; try { result = JSON .parse (data); } catch (e) { result = data; } return result; } export function onTest (callback ) { eventsListenerAdder ({ listenerName : 'test' , callback, methodName : 'onTest' parser : eventDataParser }); } export function offTest (callback ) { eventsListenerRemover ({ listenerName : 'test' , callback, methodName : 'offTest' }); } import {onTest, offTest} from './test' ;define ('swan-extension' , ['swan' , 'boxjs' ], function (require , module , exports , define, swan, boxjs ) { module .exports = { name : 'hostA' , methods : { onTest : { method : onTest }, offTest : { method : offTest } } components : {}, customLog (swanEventFlow ) {}, getCanIUseMap : () => {} }; });
扩展百度 APP 私有 API
仅限开源部分的百度 APP 私有 API
前面的章节主要介绍了扩展 API 的方式,宿主私有 API 和百度 APP 私有 API 均可以使用上述方式来进行扩展,但是百度 APP 私有 API 由于优化升级的原因,升级前后的扩展方式略有差异,接下来将阐述这些差异。
从百度智能小程序 SDK 2.23.0 开始,优化升级了私有 API,我们将升级前的 SDK 版本称为老版本,升级后的称为新版本。
老版本 老版本下,小程序框架与百度 APP 的 extension 是分离的,即百度 APP 私有 API 的部分是通过 extension 来注入的,因此宿主必须使用前端 extension 注入的方式来扩展百度 APP 私有 API。
宿主在自己的 extension 中维护想要扩展的百度 APP 私有 API 的描述表及方法。具体可参照以下示例。
extension.js 举例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 define ('test-extension' , ['swan' , 'boxjs' ], function (require , module , exports , define, swan, boxjs ) { module .exports = { name : 'baidu' , hostMethodDescriptions : [ { 'name' : 'baidu.commonDescriptionExample' , 'authority' : 'swanAPI' , 'path' : '/commonDescriptionExample' , 'args' : [ {name : 'test' , value : 'string' }, {name : 'extension' , value : 'string=' } ] } ], methods : { commonDescriptionExample : { scope : 'root' , method (args = {} ) { const {filter, parser, isCbRequired} = self.baiduPrivateMethodMap [apiName]; let params = {...args}; if (filter) { params = filter (params); } if (apiName.match ('Sync' )) { return self.boxjs [`baidu.${apiName} ` ](params); } let cbPromise = isCbRequired ? cbManager.createCbPromise (params, parser || JSON .parse ) : null ; const invokePromise = self.boxjs [`baidu.${apiName} ` ](params); const promise = isCbRequired ? [invokePromise, cbPromise] : invokePromise; executeCallback ({ promise, apiName }, params); } } } }; });
新版本 新版本下,智能小程序运行时通过宿主客户端维护的描述表进行描述表的注入和方法的挂载,同时宿主客户端需要进行相应端能力的实现,即前端无需做额外的扩展即可实现 API 的扩展。
因此对于曾经使用上述老版本的方式接入的宿主,我们推荐对百度智能小程序 SDK 进行升级,从而降低百度 APP 私有 API 的扩展和维护成本。具体的升级方式如下:
假设当前的 extension.js 如下,此时假设宿主的名字为 hostA:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 define ('test-extension' , ['swan' , 'boxjs' ], function (require , module , exports , define, swan, boxjs ) { module .exports = { name : 'hostA' , hostMethodDescriptions : [ { 'name' : 'baidu.commonDescriptionExample' , 'authority' : 'swanAPI' , 'path' : '/commonDescriptionExample' , 'args' : [ {name : 'test' , value : 'string' }, {name : 'extension' , value : 'string=' } ] } ], methods : { commonDescriptionExample : { scope : 'root' , method (args = {} ) { const {filter, parser, isCbRequired} = self.baiduPrivateMethodMap [apiName]; let params = {...args}; if (filter) { params = filter (params); } if (apiName.match ('Sync' )) { return self.boxjs [`baidu.${apiName} ` ](params); } let cbPromise = isCbRequired ? cbManager.createCbPromise (params, parser || JSON .parse ) : null ; const invokePromise = self.boxjs [`baidu.${apiName} ` ](params); const promise = isCbRequired ? [invokePromise, cbPromise] : invokePromise; executeCallback ({ promise, apiName }, params); } } } }; });
那么升级为新版本后,前端 extension.js 中维护的描述表和方法删除即可,即上述的 extension.js 修改为
1 2 3 4 5 6 7 8 9 10 11 12 define ('test-extension' , ['swan' , 'boxjs' ], function (require , module , exports , define, swan, boxjs ) { module .exports = { name : 'hostA' , hostMethodDescriptions : [], methods : {} }; });