[分享] watchFile 陷阱與進階討探 (Node.js), watchFile tricky way on Node.js

watchFile 陷阱與進階討探

這兩天因為之前寫得一個 simple-livereload 無法支援 Windows, Mac ,開始進行小改版,也稍微對 file systemPath 做些小小測試,其中發現了一個關於 watchfile 小小的問題。

問題探討

先來看一下程式碼

var fs = require('fs');<br></br>var fullpath = '/home/clonn/test.html';<br></br><br></br>fs.watchFile(fullpath, function (curr, prev) {<br></br> console.log('file update')<br></br>});<br></br>

接著進行檔案執行之後,會發現出現一個問題,當我修改 test.html 的時候,照理來說應該只有出現一次 file update ,可是卻出現 兩次 ,這實在有點不合乎邏輯。
拜了一下 Google 大神之後,終於找到原因,因為 file system 的 watchFile 實做,當關注的檔案片段(data chunk) 被更動的時候,就會觸發(trriger),接著檔案修改完成,又會重新觸發一次事件,所以導致當一個檔案修改,會被觸發兩次。

處理方法

在 filewatch 的 listen 事件當中會提供 curr, prev,之前和目前的物件(Object) ,接著使用此事件進行時間比對,所以剛才的檔案我們修改如下,

var fs = require('fs');<br></br>var fullpath = '/home/clonn/test.html';<br></br><br></br>fs.watchFile(fullpath, function (curr, prev) {<br></br> if (curr.mtime.getTime() !== prev.mtime.getTime())<br></br> console.log('file update');<br></br>});<br></br>

如此就可以得到正確結果,檔案修改,就只會進行一次觸發。

進階處理

其實 fs.watch, fs.watchFile 會回傳 listener 物件,如果要使用可以將程式碼修改如下,

var fs = require('fs');<br></br>var fullpath = '/home/clonn/test.html';<br></br>var listen = fs.watchFile(fullpath, function (curr, prev) {});<br></br>listen.on('change', , function (curr, prev) {<br></br> if (curr.mtime.getTime() !== prev.mtime.getTime())<br></br> console.log('file update');<br></br>});<br></br>

這樣的好處是在于,可以對於此物件進行處理,同時使用事件包裝等方式,讓 listen 可以重複被使用。
剛才的程式如果稍嫌太長,可以在 callback 裡面稍微修改一下

if (+curr.mtime !== +prev.mtime) <br></br> console.log('file update');<br></br>

會得到相同效果,主要是 JavaScript 的 Date type 轉型處理,當進行運算時,會自動轉為 Number,前面增加一個 + 就會進行加號運算。

結語

Node.js v0.8.0 在這次對於 file system 的效能加強許多,同時檔案的監控,尋找都可以支援跨平台(windows, Mac, linux),用來開發一些跨平台管理工具,是個不錯的選擇。

Node.js Taiwan

如果對於此篇內容有任何問題,歡迎透過 Node.js 台灣社群進行討論

參考資料

程式碼參考

CaesarChi

Web developer, focus on website fullstack, special JavaScript, and love sharing developing experience and communicate with developers. http://about.me/clonn