《Cordova》框架你們應該都不陌生,它是用來構建JSBridge的一個框架,除了Cordova之外,咱們耳熟能詳的還有《WebViewJavascriptBridge》框架也是用來解決這個問題。他們有個共同特色,就是不約而同的使用了URL攔截的方式構建的bridge。然而URL攔截的方式並不安全,可是這兩個框架使用起來是安全的,那麼以Cordova爲例,它是怎麼處理這個問題的?仍是說就沒有處理?關於這個問題,實際上Cordova框架內部是作了處理的,本篇主要針對Cordova對於URL攔截方式進行通訊作了哪些優化(曲線救國)
進行分析。前端
Cordova在iOS端是怎麼通訊的,我以前的文章《iOS 源碼解讀 -- cordova-ios》講的很清楚了,在iOS端主要是圍繞着一個queue數組進行的,具體怎麼進行的本篇不作分析了,具體能夠看前面提到的文章瞭解下。java
本篇主要圍繞如下三點進行分析爲何叫曲線救國:ios
真相都在cordova.js裏面,做爲一個未入門的前端來講,對於cordova.js只能作一個簡要分析,主要是針對上面提到的三點,看代碼。json
function iOSExec() {
//刪除了一些不在本篇討論範圍內的代碼
var command = [callbackId, service, action, actionArgs];
commandQueue.push(JSON.stringify(command));
if (!isInContextOfEvalJs && commandQueue.length == 1) {
pokeNative();
}
}
複製代碼
在js端調用cordova插件的時候,代碼會走進cordova.js裏面的這個方法,push()函數實際上就是OC中的addObject:操做,commendQueue爲cordova.js內維護的全局數組,commandQueue.push就是像commendQueue數組的最後面添加了一個對象,也就是被轉爲json格式的command對象。那麼實際上在前端連續屢次頻繁的調用插件的時候,插件的command信息都會被存儲在commandQueue中而不是把每個通訊都要去作一個假請求。經過if (!isInContextOfEvalJs && commandQueue.length == 1)這個判斷能夠看到若是commandQueue中的調用次數不爲一,也就是說可能有多個的時候,是不會執行pokeNatie()的,pokeNative實際爲發送假請求的具體實現,後面會講到。從而也就避免了插件被頻繁調用所引發的通訊丟失的狀況。數組
那麼問題來了,插件的調用都被存儲在了commandQueue中,native端怎麼獲取。這也是咱們要討論的第二個問題。安全
那麼這個問題咱們須要分析下另外一個函數,看代碼:bash
iOSExec.nativeFetchMessages = function() {
if (failSafeTimerId) {
clearTimeout(failSafeTimerId);
failSafeTimerId = 0;
}
if (!commandQueue.length) {
return '';
}
var json = '[' + commandQueue.join(',') + ']';
commandQueue.length = 0;
return json;
};
複製代碼
這是native端收到cordova.js的pokeNative發出的假請求會調用的函數,這個json對象存儲的正是commandQueue中的插件調用信息,那麼不難看出,實際上Cordova內通訊參數並非在URL上傳遞,而是JS端告訴Native過來取,大概意思就是我這有好多都取過去吧。實際上只pokeNative()了一次,那麼插件調用就都被native端取走了,這樣也就避免了快速的頻繁的發假請求而致使通訊丟失問題。框架
實際上通過了上面兩步,仍是不夠安全的,由於有一種狀況,那就是當前端的第一次調用恰好結束的時候發生了第二次調用,這個時候已經執行了commandQueue.length = 0;函數,也就是說commandQueue已經被清空了,那麼就會執行pokeNative()函數,去發一個假請求給native端,這樣就致使了連續的兩次假請求發生。實際上這一塊cordova.js也是作了處理的,詳情在pokeNative()裏面,看代碼:函數
function pokeNative() {
//代碼刪減部分
failSafeTimerId = setTimeout(function() {
if (commandQueue.length) {
// CB-10106 - flush the queue on bridge change
if (!handleBridgeChange()) {
pokeNative();
}
}
}, 50);
}
複製代碼
setTimeout()函數在javaScript裏面至關於添加了個定時器,也就是在50毫秒以後再執行pokeNative()函數,這樣也就是作了一個50毫秒的間隔,從而避免了快速的兩次調用。這一塊pokeNative()函數內部代碼註釋也有解釋,通訊效率會下降7%,可是畢竟這種狀況很少,並且7%也在咱們能接受的範圍內。post
經過上面的三部分,應該很明顯的看到了爲了構建這個bridge並保證他的安全性,是下了一番苦工的。基於URL攔截的方式,隨着JSCore和WKWebView的新特性的出現也正在被逐漸的取締,可是Cordova框架不僅僅給咱們提供了一種通訊方式,更多的是它的設計思想,以及對hybrid框架的交互設計理念,若是有一天須要咱們本身來作hybrid框架,我認爲除了改變一下通訊方式之外,對於Cordova框架的其餘部分都是很值得咱們去學習的。
本文屬於原創,轉載註明出處。