深刻淺出ghostbuster剖析NodeJS與PhantomJS的通信機制html
蔡建良 2013-11-14node
一. 讓咱們開始吧c++
經過命令行來執行web
1) 進行命令窗口: cmd數組
2) 進入resources-requested.js 所在目錄:瀏覽器
cd 你的目錄\ghostbuster\ghostbuster-master\tests緩存
3) 執行nodejs代碼: node resources-requested.jswebsocket
執行成功後,會在tests目錄下會生成一個google.png圖片。socket
resources-requested.js函數
這是一個nodejs的主文件,調用ghostbuster.js模塊,用於對網頁進行操做,代碼以下:
ghostbuster.js
這是一個nodejs的文件,導出一個spawn方法。代碼以下。
bridge.js
這是一個phantomjs的文件,代碼以下。
代碼下載: http://download.csdn.net/detail/janehlp/6552571
二. 代碼解析
ghostbuster.spawn方法傳入兩個參數,一個是端口號8089,另外一個是匿名的回調函數function(phantom){….},回調函數在ghostbuster.spawn方法內部被調用,調用時機是在socket鏈接監聽事件被觸發時發生。以下圖所示:
誰來觸發socket鏈接事件,這個固然是socket客戶端。這是通信最核心的地方。若是鏈接事件沒法被觸發,那回調函數就不會被執行。nodejs與phantomjs也沒法進行通信。
三. 觸發socket鏈接事件的真相
1) ghostbuster.spawn方法經過child_process模塊的spawn方法調用phantomjs命令來執行bridge.js代碼。phantomjs命令是一個c++寫的exe文件,該文件目錄必須在環境變量PATH中。
2) spawn(「phantomjs」,[bridge,port]執行全過程
這裏的port是傳入bridge.js中的參數。
注意:bridge.js代碼是由phantomjs解析執行,而ghostbuster.js是由nodejs解析執行,不要搞混了。二者的內置模塊是不相同的,不能混合使用。
webpage、fs、system是phantomjs內置模塊。
bridge.js代碼首先先會建立一個頁面變量controlpage,並打開http://127.0.0.1:8089網址。
這個就好像你用瀏覽器打開一個新的頁面,並在地址欄中輸入網址http://127.0.0.1:8089。
因爲前面ghostbuster.js已建立了一個http服務,監聽端口是8089。所以http://127.0.0.1:8089由ghostbuster.js中的http服務來響應,響應代碼以下圖:
ghostbuster.js中的http服務響應http://127.0.0.1:8089請求,並返回一個text/html格式的網頁內容。網頁內容來自conrolPage變量,該變量由getControlPage()方法賦值。
getControlPage()方法返回什麼呢?
nodejs與phantomjs經過websocket來進行通信。它們之間溝通的橋樑客戶端頁面,客戶端頁面至關於一個client.html文件。這個文件的內容以下:
getControlPage()方法就是返回上面這個client.html的內容,方法以下圖所示:
仍是回到bridge.js代碼中來,當phantomjs執行bridge.js,會生成一個相似client.html的頁面。
而這個頁面中採用了socket.io來與服務端創建websocket鏈接,從而實現了與nodejs的通信。
client.html執行以下腳本與node服務端鏈接,鏈接成功後會觸發connection事件,回調函數也會被執行。
注意:ghostbuster.js就是所謂的服務端。
咱們再來看看ghostbuster.js中鏈接事件被觸發後回調函數的樣子。
四. 頁面建立完整過程
callback(p)執行的是resources-requested.js中的回調方法function(phantom){…}。
function(phantom){…}方法使用ghostbuster中p對象的createWebPage來建立頁面。
操做網頁以前必須先建立一個空白頁面,而後再打開網址並進行其它操做。
function(phantom)這個方法中的參數phantom是ghostbuster.js中的變量p。p這個對象封裝了phantomjs命令。讓咱們看看對象p封裝了哪些方法。
對象p封裝了3個屬性和5個方法。其中createWebPage是用於建立頁面。
讓咱們更深刻了解一下建立頁面的完整過程:
1) resources-requested.js執行p對象中的createWebPage方法。
2) ghostbusert.js執行p. createWebPage方法,並調用了request方法。
參數說明: properties爲{settings:{loadImages:true}},callback爲function(page){…}。
3) ghostbusert.js執行request方法,調用socket發出cmd命令。
參數說明:args爲[「createWebPage」,properties],callback爲function(page){…},cbId爲空。
args.splice(0,0,cbId); 是指從第0個位置開始插入 cbId,即回調函數的索引。
將回調函數緩存到requests數組,後面responseHandler方法還須要用到。
4) client.html頁面接收到cmd命令,並執行alert(msg)方法。
參數說明: msg爲[cbId,「createWebPage」,properties]
5) bridge.js監聽controlpage頁面的alert事件,並執行createWebPage(msg)方法。
參數說明: message爲[cbId,「createWebPage」,properties]
6) bridge.js執行createWebPage(msg)方法建立頁面對象,並調用respond方法返回信息。
參數說明: req爲[cbId,「createWebPage」,properties]數組對象。
req[0]爲cbId。index爲頁面索引。
7) bridge.js執行respond(args)方法經過頁面的evaluate方法發送socket命令向nodejs服務端發送響應信息。
參數說明: args爲[cbId,「createWebPage」,index]
8) ghostbuster.js經過socket.on(「res」,responseHandler)對res命令設置監聽處理responseHandler。
參數說明:response爲字符串,值爲[cbId,「createWebPage」,index]。
cb爲resources-requested.js中的回調函數function(page) {…}。res爲頁面索引index。
WebPage方法在ghostbuster.js中定義以下:
9) resources-requested.js的回調函數function(page) {…}。
終於又回到主程序來了,這時咱們能夠經過WebPage對象來對頁面作具體的業務功能,如打開一個頁面進行截屏等操做。
五. 頁面建立流程圖