1 jsbridge promise 封装
/*
* @Author: zhangyu
* @Email: zhangdulin@outlook.com
* @Date: 2021-06-11 11:00:48
* @LastEditors: zhangyu
* @LastEditTime: 2021-06-16 18:07:04
* @Description:
*/
//JS注册事件监听
var initflag = false
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
}
//注册回调函数,第一次连接时调用 初始化函数
// connectWebViewJavascriptBridge(function(bridge) {
// //初始化
// bridge.init(function(message, responseCallback) {
// initflag = true
// var data = {
// 'Javascript Responds': 'Wee!'
// };
// // alert("jasdashjd");
// responseCallback(data);
// });
// })
/**
* @description: jsbridge callHandler
* @param {*} callHandlerData
* @param {*} name n请求的方法
* @param {*} data 请求时传的参数
* @return {*} function
*/
export function callHandler (callHandlerData={name:'', data:{}}) {
let _resolve
let _reject
// 生成promise对象,保留resolve,reject
const readyPromise = new Promise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
connectWebViewJavascriptBridge(function(bridge) {
//初始化
if (!initflag) {
bridge.init(function(message, responseCallback) {
initflag = true
var data = {
'Javascript Responds': 'Wee!'
};
responseCallback(data);
});
try {
bridge.callHandler(callHandlerData.name, callHandlerData.data, (response) => {
// 调用成功,使用保留的resolve改变返回的promise状态
_resolve(response)
})
} catch (e) {
// 调用成功,使用保留的reject改变返回的promise状态
_reject(e)
}
} else {
try {
bridge.callHandler(callHandlerData.name, callHandlerData.data, (response) => {
// 调用成功,使用保留的resolve改变返回的promise状态
_resolve(response)
})
} catch (e) {
// 调用成功,使用保留的reject改变返回的promise状态
_reject(e)
}
}
})
return readyPromise
}
/*
* @Author: zhangyu
* @Email: zhangdulin@outlook.com
* @Date: 2021-06-11 11:00:48
* @LastEditors: zhangyu
* @LastEditTime: 2021-06-11 14:05:50
* @Description:
*/
// 注册方法获取WebViewJavascriptBridge对象
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(window.WebViewJavascriptBridge)
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback)
}
// 兼容安卓
document.addEventListener(
'WebViewJavascriptBridgeReady',
() => callback(window.WebViewJavascriptBridge),
false
)
// 兼容ios
window.WVJBCallbacks = [callback]
var WVJBIframe = document.createElement('iframe')
WVJBIframe.style.display = 'none'
WVJBIframe.src = 'https://__bridge_loaded__'
document.documentElement.appendChild(WVJBIframe)
setTimeout(function() {
document.documentElement.removeChild(WVJBIframe)
}, 0)
}
// 获取WebViewJavascriptBridge对象
function getBirdge() {
return new Promise(resolve => {
if (window.WebViewJavascriptBridge) {
return resolve(window.WebViewJavascriptBridge)
}
setupWebViewJavascriptBridge(bridge => {
// 初始化
bridge.init(function(message, responseCallback) {
var data = {
'Javascript Responds': 'Wee!'
};
responseCallback(data);
});
resolve(bridge)
})
})
}
// 重写之后的birdge
/**
* @description: jsbridge callHandler
* @param {*} callHandlerData
* @param {*} name n请求的方法
* @param {*} data 请求时传的参数
* @return {*} function
*/
export default {
ctx: null, // WebViewJavascriptBridge
callHandler(callHandlerData={name:'', data:{}}) {
return new Promise(async resolve => {
if (!this.ctx) {
this.ctx = await getBirdge()
}
this.ctx.callHandler(callHandlerData.name, callHandlerData.data, res => resolve(res))
})
},
registerHandler(jsHandlerName) {
// 重写事件注册方法
this.ctx.registerHandler(jsHandlerName, (data, callback) => {
if (callback) {
callback(
`返回一个字符串,告诉ObjC:我已收到数据${JSON.stringify(data)}`
)
}
})
}
}
2 dsbirdge 性能更好 写法优雅 原生ios 安卓统一规范
npm 引入
npm i dsbridge
测试例子
<!--
* @Author: zhangyu
* @Email: zhangdulin@outlook.com
* @Date: 2021-06-18 10:41:17
* @LastEditors: zhangyu
* @LastEditTime: 2021-06-18 10:41:17
* @Description:
-->
<!DOCTYPE html>
<html>
<head lang="zh-cmn-Hans">
<meta charset="UTF-8">
<title>DSBridge Test</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no"/>
<!--require dsbridge init js-->
<script src="https://cdn.jsdelivr.net/npm/dsbridge/dist/dsbridge.js"> </script>
</head>
<style>
.btn {
text-align: center;
background: #eee;
color: #000;
padding: 20px;
margin: 30px;
font-size: 24px;
border-radius: 4px;
box-shadow: 4px 2px 10px #999;
}
.btn:active {
opacity: .7;
box-shadow: 4px 2px 10px #555;
}
</style>
<body>
<div class="btn" onclick="callSyn()">Synchronous call</div>
<div class="btn" onclick="callAsyn()">Asynchronous call</div>
<div class="btn" onclick="callSynSwift()">Syn call (swift)</div>
<div class="btn" onclick="callAsynSwift()">Async call(swift)</div>
<div class="btn" onclick="callNoArgSyn()">Sync call without argument</div>
<div class="btn" onclick="callNoArgAsyn()">Async call without argument</div>
<div class="btn" onclick="echoSyn()">echo.syn</div>
<div class="btn" onclick="echoAsyn()">echo.asyn</div>
<div class="btn" onclick="callAsyn_()">Stress test,2K times consecutive asynchronous API calls</div>
<div class="btn" onclick="callNever()">Never call because without @JavascriptInterface
annotation<br/>( This test is
just for Android ,should be ignored in IOS )
</div>
<div class="btn" onclick="callProgress()">call progress <span id='progress'></span></div>
<div class="btn" onclick="hasNativeMethod('xx')">hasNativeMethod("xx")</div>
<div class="btn" onclick="hasNativeMethod('testSyn')">hasNativeMethod("testSyn")</div>
<script>
function callSyn() {
alert(dsBridge.call("testSyn", "Hello"))
}
function callAsyn() {
dsBridge.call("testAsyn","hello", function (v) {
alert(v)
})
}
function callSynSwift() {
alert(dsBridge.call("swift.testSyn", "hello"))
}
function callAsynSwift() {
dsBridge.call("swift.testAsyn","hello", function (v) {
alert(v)
})
}
function callAsyn_() {
for (var i = 0; i < 2000; i++) {
dsBridge.call("testAsyn", "js+" + i, function (v) {
if (v == "js+1999 [ asyn call]") {
alert("All tasks completed!")
}
})
}
}
function callNoArgSyn() {
alert(dsBridge.call("testNoArgSyn"));
}
function callNoArgAsyn() {
dsBridge.call("testNoArgAsyn", function (v) {
alert(v)
});
}
function callNever() {
alert(dsBridge.call("testNever", {msg: "testSyn"}))
}
function echoSyn() {
// call function with namespace
var ret=dsBridge.call("echo.syn",{msg:" I am echoSyn call", tag:1});
alert(JSON.stringify(ret))
}
function echoAsyn() {
// call function with namespace
dsBridge.call("echo.asyn",{msg:" I am echoAsyn call",tag:2},function (ret) {
alert(JSON.stringify(ret));
})
}
function callProgress() {
dsBridge.call("callProgress", function (value) {
if(value==0) value="";
document.getElementById("progress").innerText = value
})
}
function hasNativeMethod(name) {
alert(dsBridge.hasNativeMethod(name))
}
dsBridge.register('addValue', function (r, l) {
return r + l;
})
dsBridge.registerAsyn('append', function (arg1, arg2, arg3, responseCallback) {
responseCallback(arg1 + " " + arg2 + " " + arg3);
})
dsBridge.registerAsyn('startTimer', function (responseCallback) {
var t = 0;
var timer = setInterval(function () {
if (t == 5) {
responseCallback(t)
clearInterval(timer)
} else {
// if the 2nd argument is false, the java callback handler will be not removed!
responseCallback(t++, false)
}
}, 1000)
})
// namespace test for syn functions
dsBridge.register("syn", {
tag: "syn",
addValue:function (r,l) {
return r+l;
},
getInfo: function () {
return {tag: this.tag, value:8}
}
})
// namespace test for asyn functions
dsBridge.registerAsyn("asyn", {
tag: "asyn",
addValue:function (r,l, responseCallback) {
responseCallback(r+l);
},
getInfo: function (responseCallback) {
responseCallback({tag: this.tag, value:8})
}
})
</script>
</body>
</html>