From cb35707c34ba02abb0fcb27899811a4eb0c3ad6e Mon Sep 17 00:00:00 2001 From: Tevin <tingquanren@163.com> Date: Mon, 22 Feb 2021 10:57:57 +0800 Subject: [PATCH] APP通讯初始化,第一步 --- common/Bridge.js | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 200 insertions(+), 0 deletions(-) diff --git a/common/Bridge.js b/common/Bridge.js index e69de29..f1cec46 100644 --- a/common/Bridge.js +++ b/common/Bridge.js @@ -0,0 +1,200 @@ +/** + * 跨端双向通讯桥 + * @author Tevin + * @tutorial + * 网页对 app 发起通讯 + * 1. app 注册接收机制 + * app 在网页打开之前,注入方法 linking + * 2. js 发起 + * bridge.invoking('methodName', {key1:'value1'}, function(res){console.log(res)}); + * 3. Bridge 转换为发送 + * window.linking('{method:\'methodName\', param:{key1:\'value1\'}, callback:\'bridge.cb111at1541994536008\'}'); + * 4. app 处理完后直接调用网页上的回调,并传递结果 + * bridge.cb101at1541994536008('{key2:\'value2\'}'); + * app 对网页发起通讯 + * 1. 网页注册接收器,用于接收 app + * window.telling = function(dataStr) {}; + * 2. 网页注册业务 + * bridge.register('methodName', function(data, callback){}); + * 3. app 调用(至少需要在页面完成再延迟至少1秒之后) + * telling('{method:\'methodName\', param:{key1:\'value1\'}, marker:\'mk222at1541994536008\'}'); + * 4. 网页完成业务逻辑处理,并回调 + * window.linking('{method:\'methodName\', param:{key2:\'value2\'}, marker:\'mk222at1541994536008\'}'); + */ + + +export class Bridge { + + constructor() { + this._data = { + count: 100, + }; + this._receives = {}; + this._init(); + } + + /** + * 检查 linking 方法 + * @return {string} + * @private + */ + _checkLinking() { + // 安卓注入 + if (window.iTop && window.iTop.linking) { + return 'android'; + } + // 没有注入 + else { + return ''; + } + } + + /** + * 初始化 + * @private + */ + _init(count = 0) { + // 500 * 20 毫秒后,仍然未注入,视为不工作 + if (!this._checkLinking() && count < 20) { + setTimeout(() => { + this._init(++count); + }, 500); + } else { + this._initReceive(); + } + } + + /** + * 发送 + * @param {object} data + * @private + */ + _send(data) { + const platform = this._checkLinking(); + // 安卓注入 + if (platform === 'android') { + window.iTop.linking(JSON.stringify(data)); + } + // 没有注入 + else { + console.error('没有注入 linking 方法!'); + } + } + + /** + * 发起一次发送 + * @param {string} method + * @param {object} param + * @param {function} callback - 来自网页业务逻辑的回调 + * @private + */ + _sendLinking(method, param, callback) { + // 数据检查 + if (Object.prototype.toString.call(param) !== '[object Object]') { + console.error('$bridge.invoking 需要接受 JSON 对象!'); + return; + } + // 如果有回调,转存回调 + const name = 'cb' + this._data.count++ + 'at' + Date.now(); + this[name] = (res) => { + if (callback && Object.prototype.toString.call(callback) === '[object Function]') { + if (res) { + const data = typeof res === 'string' ? JSON.parse(res) : res; + callback(data); + } else { + callback(); + } + } + delete this[name]; + }; + // 发送 + this._send({ + method, + param, + callback: 'bridge.' + name, + }); + } + + /** + * 向 app 发起通讯 + * @param {string} method + * @param {object|function} [param] + * @param {function} [callback] + */ + invoking(method, param, callback) { + const trans = param; + if (trans) { + if (Object.prototype.toString.call(trans) === '[object Function]') { + callback = trans; + param = {}; + } + } else { + callback = null; + param = {}; + } + this._sendLinking(method, param, callback); + } + + /** + * 初始化接收 + * @private + */ + _initReceive() { + if (!this._checkLinking()) { + return; + } + window.telling = (res) => { + const data = typeof res === 'string' ? JSON.parse(res) : res; + const method = data.method; + const param = data.param; + const marker = data.marker; + if (this._receives[method]) { + this._receives[method](param, (param2) => { + this._sendTelling(method, param2, marker); + }); + } + }; + } + + /** + * 发送响应 + * @param {string} method + * @param {object} param + * @param {string} marker + * @private + */ + _sendTelling(method, param, marker) { + // 数据检查 + if (Object.prototype.toString.call(param) !== '[object Object]') { + console.error('$bridge.register 注册的函数需要接受 JSON 对象!'); + return; + } + // 发送 + this._send({ + method, + param, + marker, + }); + } + + /** + * 注册接收指令,可供 app 查询 + * @param method + * @param callback + */ + register(method, callback) { + this._receives[method] = callback; + } + + /** + * 是否有开始工作 + */ + isWorking() { + const platform = this._checkLinking(); + return platform === 'android' || platform === 'iOS'; + } + +} + +// 全局服务实例 +export const $bridge = new Bridge(); -- Gitblit v1.9.1