發表文章

目前顯示的是有「NodeJS」標籤的文章

Node.js 裡的 JavaScript Array 非同步操作

如果你原本是一個專業的前端工程師,或許在 Node.js 出來之後,便開始嘗試了 Server 程式的開發。然後發現,使用 JavaScript 開發 Server 程式的過程中,有很多的細節應該注意,尤其是碰上處理大量資料和 I/O 操作時,更要對 JavaScript 引擎的運作原理有一定程度的理解。因為,絕大多數的問題,都是出在非同步(Asynchronize)與同步(Synchronize)的機制上。 許多開發人員,都會認同在開發 Node.js 程式時,盡可能、甚至絕對不要使用『同步』的方法和 API,因為,那會打亂 JavaScript 事件引擎的運作,產生各種詭異的後疑症,而且非常難以除錯。如果你發現你的程式會莫明自己結束,或是程式運作的流程不如預期,可能就是掉入了『同步』與『非同步』的陷阱了。 如果你稍微翻過文件,就會發現,其實 Node.js 本身對很多的 API,已經同時提供了『同步』與『非同步』兩種版本供開發者使用。不過,雖然 Node.js API 都有提供『非同步』版本,但是有些根本東西,卻欠缺『非同步』的方法,像是本文標題所提到的『Array』,就是其中之一。 針對 Array 的諸多操作,最常見的莫過於 forEach 方法,用來處理每一個 Array item: var arr = [ 1, 2, 3, 4 ]; arr.forEach(function(element, index, arr) { // Processing }); console.log('Completed'); 然而,這個方法是『同步(Synchronize)』,也就是會讓整個程式阻塞,等所有 Array item 讀出和處理完之後,才顯示最後的『Completed』字串。 類似的東西,不少人也會使用純 for-loop 來實作,但也都是一樣的狀況: var arr = [ 1, 2, 3, 4 ]; for (var i in arr) { // Processing } console.log('Completed'); 想想看,如果 Array item 的數量相當多,又或者是每個 item 的處理時間相當長,整支程式會像死當一樣沒反應。要知道,讓一段程式跑太久,是 Event...

夢想偉大,但步伐短小的 DBHouse

數個月前開始做一個計劃『AppHouse』,實作如 Google App Engine(GAE) 般的 PaaS,其志在打造自己的 Node.js 雲端軟體平台。然後發現,除了讓雲端服務可以在平台上跑起來外,資料庫管理也必需有個便於使用的機制和規劃,仔細想想,一個沒有資料庫配合的雲端服務,可沒有什麼太大的價值,於是,『DBHouse』便應運而生。 你可以在 github 上找到這個專案: https://github.com/Mandice/node-dbhouse DBHouse 起初的開發目的,是讓使用 AppHouse 架設以及開發自己雲端服務的人,可以很容易存取資料庫。此外,對我們而言更便於管理資料庫資源,面對許多不同的服務,不需要特別為他們開設資料庫權限,亦或是買許多硬體和主機,建立起許多 VM 並做各種安全性規劃。其實,如果把 DBHouse 的用途,想像成 Google 在做的事,就很容易明白:『在 GAE 上你可以使用統一的 Database APIs,存取 Google 提供的資料庫系統(BigTable)。』,同理,我們也是在做同樣的事。 只不過,學 Google 開發自己的一套資料庫太過於困難,不是一個可以達成的目標,所以我們仍然選用 MongoDB 當做 PaaS 的資料庫底層。僅管資料庫不是自己開發的,我們還是可以提供統一的 API,讓開發者存取。統一的 API 有個好處,若能做到當開發者在使用的時候,不需要知道自己在使用什麼資料庫,日後就可以在這 API 之後串接或替換不同的資料庫系統,有很大的彈性可以擴充。 當然,更遠大的目標是希望在一個 Table(Collection) 內,因應不同的欄位需求,而交由不同資料庫處理,更進一步發揮不同資料庫的特色。但是,這夢想遠大,技術上也有很多盲點待討論,所以能不能實現那是另外一回事,至少,短期內在我們的能力範圍和經濟狀況下,暫時無法達成這一步。 雖然 DBHouse 有這樣的初衷和夢一般的計劃,但不代表 DBHouse 一定得和 AppHouse 配合使用,更準確的說,他們本來就是獨立各自發展的專案,各自可獨立運作。說穿了,DBHouse 本身就只是一個 Database API,你可以在 Node.js 裡使用 DBHouse API 去操作自己的 MongoDB(目前只有支...

一起來用 Courser 吧!管理 Route 的利器!

跳脫出前端應用之後的 JavaScript 語言,所遭遇的挑戰極大,至今還沒有一個非常好的開發模型和原則,讓人不免抱怨。因為沒有前人可學習,也沒有太多文獻可以參考,所以,為了讓自己能夠更快完全領會 JavaScript 在各種極端環境之下的開發情況,在這一年來,花了相當多的時間投入去做各種不同類型的 Project,從 Web service、Embedded System、System Programming 到各式雲端技術開發,嘗試從中累積更多用 JavaScript 打天下的經驗。唉,慣 C 都不慣 C 了。 不過,做了許多東西後,就會開始有機會重覆開發相同的功能,這時就會希望能重覆利用舊的程式碼,讓同一段程式,不用每次都重寫一次而浪費時間。於是,開始慢慢把之前做過的專案整理,然後整併許多功能,獨立出來變成一個個 Node.js 模組。 Courser 就是這樣被獨立出來的專案,而功能是為 Express Web Framework 提供一個管理 HTTP Routing 的方案。你可以從 github 上找到專案首頁: https://github.com/cfsghost/courser Express 範例的傳統做法,是每次增加一個 API 或頁面,就要更動一次主程式檔案(app.js),以管理 HTTP Routing,相當麻煩,尤其當有許多人協同開發時,更多不必要的程式碼衝突便出現了。此外,管理專案中的 Handler 也是件麻煩事,因為我們總不可能將所有的 Handler 寫在同一支檔案裡,必須適當分類分檔,才能便於維護。隨著專案規模越來越大,需求越來越複雜,這便是件苦差事。 這些問題當然有解決方案,Express Source Code 裡的範例,就提供了幾種不同的方法,供開發者參考,只不過,這些方法大部份很簡陋、不通用,多半還是要靠專案開發者自行想辦法,開發一套機制,才能解決需求。因此,之前為了專案的需要,就實作了 Courser 去管理專案下的 HTTP Routing 和所有的 Handler,嘗試讓 routes 不要每次開發出來,都是這麼醜。 Courser 目前已經釋出 v0.0.2,你可以從 NPM 上直接安裝它: npm install courser 假設你已經會使用 Express Web ...

GNOME.Asia Summit 2012 香港遊之簡報釋出

最近因為忙錄,遲遲未寫下今年六月初飛去香港(Hong Kong)參加 GNOME.Asia 2012 的心得,以及將當時在活動中的簡報檔釋出。:-) 對一個台灣來的人而言,香港不會讓人感到陌生,若不說新發展的地方,走在街頭,讓人有走在台北西門町的感覺,或是像台灣一些繁華的老市區以及夜市,站在路中央看過去,當下可以感受到早期台灣和香港之間的微妙關係,其共同點難以言喻。事實上,除了廣東話,還有那些銅板和五花八門的紙鈔外,沒有什麼會讓台灣人不習慣的地方。 話說回來,今年的 GNOME.Asia 2012 是在香港城市大學舉行,據當地朋友所說,這是一個與大型商場(百貨公司)纏綿的學校,由於學校、商場和交通樞紐的動線很密切,走在裡面,你會感覺到商場就像學校的一部份,走沒有幾步路,就會走入了商人的魔掌,錯進了名牌服飾的專櫃。 不過,身為一個宅宅開發者,當然不會被這些名牌服飾所迷惑,它們是嚇不倒我的!活動,當然才更重要! 我能了解,很多人在今天看到 GNOME 幾個大字就興趣缺缺,GNOME 讓大家又愛又恨,許多人不喜歡 GNOME 3 將桌面大改,像是 Linux 之父 Linus Torvalds 前些日子跳出來劈天蓋地的砲轟;也有很多人(像是我)對於許多元件被改壞或是效能不彰而感到很不悅。但由於歷史因素,太多人無法逃脫出 GNOME 所設計出來的大框架,就算你不想用 GNOME 的桌面環境,在 Linux 等 Unix-like 系統中,你還是免不了要去使用基於 GTK+/GLib 所設計的軟體,可以說 GNOME 無處不在,已經不是單單『桌面環境』一詞可以概括。 喜不喜歡新一代的 GNOME 桌面環境是其次,對於我而言, GNOME 是一座作業系統『操作機制』的兵工廠,他生產了太多元件讓我們可以自由使用,然後提供方法讓使用者和開發者可以用『人的角度』去控制作業系統。所以,如果你真的不滿意新的 GNOME 圖形介面設計,自己將 UI 打掉重練也不會是件難事。 這次去香港參加活動,見到了不同地方的開發者和使用者,尤以『中文輸入法(包括輸入框架)』這個議題特別引起討論。這些同是非英語系的 CJK 開發者和使用者們,有頗多的交流。雖然有些議程全程是以廣東話進行討論,我完全聽不懂,但好在有些坐旁邊的香港朋友自動自發充當即時翻譯,還順便介紹了許多當地輸入法開發...

Node.js v0.8 大變革?!Native Module 開發者的福音!

最近 Node.js 推出了 v0.8 穩定版,除了改善 I/O 的效能和一些 API 外,最大的變動就是跨平台開發環境的改進。包括了決定徹底使用 GYP 取代 node-waf(wscript)、宣布 libev 將死。或許,這些變動這對大部份的 Node.js 使用者來說不是什麼問題,但對於我們這些寫 Native API 和底層的開發者來說,關係到自己程式能不能跑在未來 Node.js 的新版本上,而且產生了很多移植性的工作。但是整體來說,好處其實大於壞處,因為以後我們的程式更容易跨平台了。 轉用 GYP GYP 是 Google 發展出來的 Build script tools,就像是傳統 Autotools、Makefile 或 CMake 這類的工具。GYP 最早被應用在廣為人知的 Google Chrome/Chromium Project ,是個跨平台的解決方案,這也是為什麼 Node.js 決定要採用的主要原因。 在以前,不同的平台上,你需要為 C/C++ Addon 製作不同的 Build script,沒有統一的方法和途徑去設置和編譯程式,這讓跨平台的工作非常麻煩。使用 GYP 後,可以大幅減少這樣的問題。 棄 libev ,轉用 libuv 首先,有一點要注意,Node.js 開發者打算在下一個穩定版(應該是 v1.0)拿掉 libev 的支援,所以請所有的開發者盡快轉用 libuv。 libev 是 Node.js 在非 Windows 平台上所使用的 Event loop 解決方案,讓 C/C++ 開發者可以開發 Event-driven 的程式,除了可以用來監聽 FileSystem 等用途,也更容易整合 Thread 進 Event-driven 的設計模式中,要是你有印象,GLib 其實也是類似的解決方案之一,只不過 libev 更為輕量。不過, libev 主要還是被應用在 Unix-like 的系統上,若 Node.js 要支援多個平台,在其他系統上,就必需尋求別的解決方案,如 Windows 的 IOCP。 而過去這樣的情況,對我們 Node.js Native Module 開發者來說,是個莫大的挑戰,你必需在不同系統上,採用不同的寫法,導致開發上很困難。所以 Node.js 自行開發了 libu...

實作 X11 底下的 Popup Menu

既然要投入 JavaScript 的發展,一個很重要的目標就是讓 JavaScript 能被用來開發 Native 桌面程式。而為了達成這樣的願景,我們的團隊沒日沒夜的發展各類基礎技術和擴充底階 API,甚至是將以 JavaScript 開發整個桌面環境(Desktop Environment, 如:GNOME、KDE、LXDE 或 XFCE 這類專案)為終極目標。 當然,跳出瀏覽器之後的 JavaScript,缺少了繪圖引擎,所以要拿來做圖型化使用者介面,會更為困難。慶幸的是,前些日子發展出的 jsdx-toolkit 已經解決了大多數的問題,除了有 3D、動畫等支援,也已經有了許多現代桌面有的UI元件(如:Entry、Label、Button... 等),以致我們完全可以放心的開發屬於自己的圖型化應用程式。 不過,目前的情況,在手機、平板或是特定用途的嵌入式系統中完全夠用,一旦回到更為複雜的桌面環境下,就會遭遇到許多的問題。像是回到 XWindow 底下後,會遇到許多 X11 的視窗管理機制,其視窗之間錯縱複雜的交互關係,就是我們要處理的。尤其是當我們在開發桌面環境時,就會發現在一般的桌面環境下,使用者可能會同時開無數個視窗和程式,並且隨機又大量的切換使用,這迫使我們必須去修改 jsdx-toolkit 以處理 X11 底下的更多狀況,符合並更完整支援一般桌面環境下的操作習慣。 你可能用過 GTK+/Qt 這類常見的 Toolkit,也知道在 X11 之下有很多種類型的視窗(Window),像是 Dialog、Splash、Menu、Popup Menu 等等,但你可能不知道這些現代 Toolkit 內部做了多少事。事實上,X11 本身雖定義了各類視窗的類型,但實際上 XWindow 和 Window Manager 並不會完全去照定義去處理你的視窗行為,更準確的說法是,X11 HWMH 中的基本定義和我們實際的認知是有出入的,該定義只是說希望達成的行為,但沒說是由誰(XWindow、Window Manage 還是 GUI Toolkit)去處理。 舉例來說,我們現在寫一支程式,該程式不使用任何現代的 GUI Toolkit,然後單純使用 X11 API 把一個 Window 的類型設成 Popup Menu。但是你會發現,它的實際行為並不像我...

簡單理解 JavaScript 的記憶體管理機制

不像其他的語言,JavaScript 開發者永遠沒有辦法自己去釋放記憶體,頂多只能移除物件的 Reference (代表這物件已經沒有人在使用),而且這物件所佔的記憶體並不會馬上被釋放,而是 Garbage Collection 在滿足某些條件的情況下,才在背景自動去尋找沒有被使用的物件,然後釋放。若你嘗試過尋找釋放記憶體或移除物件 Reference 的方法,得到的解答,應該不外乎是使用 delete 關鍵字或是將變數設為 null,但是你真的了解它的意義嗎?事實上,有很多人都是在不瞭解的情況下使用它們,還可能因此產生 Memory leaks 的狀況。欲弄清楚這一切,我們必須先簡單理解一下 JavaScript 的記憶體管理機制,更準確的說,是物件的管理機制。 從 JavaScript 開發者角度來看,JavaScript Engine 在運作時,記憶體使用是呈現樹狀結構,也就是所有命名或建立的變數或物件,都是存放在一個全域(global)的 Object 中。在 Node.js 中,你可以直接讀取 global 變數看到目前 Context 的環境狀態: console.log(global); 我們可以做個實驗理解一下: var myVar = 'Hello'; function myFunc() { return 123; } var myObj = { a: 1, b: 2 }; console.log(global); 執行以上程式,你應該可以從 global 中找到我們自己定義的變數和函式: { ...(已省略基本預設的環境變數)... myVar: 'Hello', myFunc: [function], myObj: { a: 1, b: 2 }, ... } 從結果可以發現,所有的物件都以樹狀的形式被 global Object 保存著,無論是變數還是任何一種類型的物件,都是一組組 Key/Value 的存在。而 Value 就是各種不同形態的物件,如字串、函數、陣列、數值等。 所以,移除某物件的 Reference,就意味著將把物件從這棵樹上拔除掉。因此,我們可以直接將該變數設為 nul...

【JSDC.tw 2012 簡報檔釋出】Non-MVC Web Framework

由於一些因素,被徵招去救火,在 JSDC.tw 2012 (JavaScript Developer Conference 2012) 給與了一場 Talk,由於準備時間相當緊迫,就把最近在研究和試驗的半成品匆匆拿上場展示和說明,題目是『Non-MVC Web Framework』。你可能在議程上沒有看到這場 Talk,實際上是因為主辦單位的一些小疏忽,議程上仍是寫著之前的舊題目『Build Node.js Module』,而且小弟的名字也打錯了,從 Fred 變成了 Frend,差一點就變成二十世紀少年的友民黨教主。:-) 本次議程其實和前幾天發的舊文『 前端工程師也可以淡定的開發網站應用!RedTea Web Framework! 』息息相關,探討的是改善 MVC 的開發流程,和引入 JavaScript/Node.js 後的大膽嘗試,而且進一步討論實作細節。此外,因為 RedTea 本身只是一個實驗性的專案,目的只在於驗證可行性,還不到實際使用程度,所以藉著這次機會,公開並宣布新專案『 Kamalan Web Framework(葛瑪蘭) 』,Kamalan 引入了 Express Web Framework 為基礎,然後將結合 RedTea 的成果,並更進一步簡化其中細節和使用方法,讓前端工程師能真正無痛上手。 雖然還沒完全將 RedTea 的機制完全整合進 Kamalan,但目前 Kamalan 最少可以和 Express 一樣使用,你如果有用 Express 寫的程式,直接將 require() 引入的模組名改成 Kamalan 即可。由於 Kamalan 在根本上就是 Express,甚至是可以使用 Express 的所有 Middleware。 後記 這場 Talk 後,引起了一些 JavaScript Developer 趕的迴響,一些建議和聽眾的期待相當令人開心,討論過程也非常愉快。感謝大家的參與。:-)

前端工程師也可以淡定的開發網站應用!RedTea Web Framework!

還記得,尚未投入 Node.js 前,一直覺得 Node.js 帶來了未來,讓我們可以用 JavaScript 同時開發 Web 前端(Front-end)和後端(Back-end),等到真的投入 Node.js 後,發現雖然事實的確是如此,但由於前端和後端應用所需要的背景知識不盡相同,開發模式和概念更是大異其趣,所以,雖然同樣是使用大家熟悉的 JavaScript 語言,但前端開發者仍然不見得能夠如願地來開發後端應用。 這樣的情況讓我想起有位來台灣工作的外國朋友,曾告訴過我一個多年前發生在他身上的笑話。故事是: 他原本是個美術方面的設計師,然後,但有一天老闆對他說:『你從現在起,去做開發程式的工作吧。』 他問:『為什麼?』 老闆回答:『寫程式是用英文寫,而你又會英文,不就可以寫嗎?』 是的,同樣道理,雖然對前端工程師而言,JavaScript 是最熟悉的程式語言,而 Node.js 又可以讓你使用 JavaScript 寫整個 Web 應用,但這不代表對這些人而言,就可以輕易上手 Web service 的後端開發。要真正讓前後端開發合而為一,不只是語言要統一,開發經驗也要相同才是,這才是所有 Web 開發者最期盼的事。 於是筆者基於 Node.js,開發了『 紅茶(RedTea) 』,這是一個和現有的網站框架(Web Framework)所不一樣的全新的嘗試。以前端開發者視角和經驗為出發點,專門設計給前端工程師上手使用的網站框架,讓前端工程師也可以『淡定』的開發網站應用。由於 RedTea 不是傳統 MVC 模型的 Framework(至於 RedTea 採用的是哪種開發模型,筆者一時也說不上來。),所以,如果你是一個已經被 MVC 涂毒已深的開發者,可能要先花點時間重新理解一下。:-) 此外,RedTea 有一個最大的特點,就是支援了在瀏覽器環境下,呼叫後端 JavaScript Class/Function 的功能,就像在使用本地端的 JavaScript 物件般。因此,前後台交換資料,不用再以 GET/POST、URL Path Routing 或 Ajax 相關的方法實作,只要學會怎麼使用 JavaScript Class 即可。重點是,即使你沒有任何 HTTP 通訊協定的知識,或後前後端資料處理的經驗,依然可以開發出網站程式。 ...

想寫好 JavaScript,遞迴技能要練好

V8 JavaScript Engine 的運作,主要是以事件驅動(Event-driven)來執行所有的程式碼,如果你有開發過 GTK+ 程式的經驗,使用上應該不陌生。不過這對一般人其實相當不好理解,因為事件驅動會讓你的程式看起來像是多工在運作(如使用執行緒),所以有些人對於 JavaScript 的理解是,有些東西可以丟背景執行。 要了解事件驅動,可以先從 JavaScript 的行為說起。如果你正在使用 Node.js,你就會發現 Node.js 通常對同樣功能提供了兩個 API,分為『同步(Synchronize)』和『非同步(Asynchronize)』兩種類型。例如下面這刪除特定檔案的例子: 同步(Synchronize) API: fs.unlinkSync('/home/fred/badfile'); ... 非同步(Asynchronize) API: fs.unlink('/home/fred/badfile', function(err) { if (err) { console.log('Failed to delete file.'); return; } console.log('Successfully delete a file.'); }); ... 簡單觀察同步與非同步的執行結果,可以知道前者(同步)會停住並阻塞在此 API,等檔案刪除成功後才繼續下一行程式;而後者(非同步)有如將刪除檔案的工作丟到背景執行,並繼續往下一行程式執行,完全不會像同步 API 一樣停住。等刪除檔案的工作完成後,便觸發事件去呼叫 Callback function。而這樣非同步的機制就全靠事件驅動(Event-driven)來達成,雖看起來像是把程式丟到背景跑,實際上是在 JavaScript Engine 上註冊了一個事件,等到工作完成以後,事件被觸發時才接續執行 callback function。 非同步的做法通常會用在需要花大量時間的 API 上,如檔案系統、資料庫系統的操作等,以避免因為單一 API 造成整個程式鎖死或卡住不會動的問題,尤以前端和需要即時反應的工作上,特別需要。 至於這樣的事件驅動是怎...

【OSDC.tw 2012 Hackathon 成果分享】用 JavaScript 打電話囉!

圖片
以為 OSDC.tw 2012 在 4/15 號時就結束了嗎?其實並沒有。在活動的一個星期後,於 4/21 星期六,OSDC.tw 接著舉行了 Hackathon 的活動。很多人可能不知道 Hackathon 是什麼,有人叫他『駭客鬆』、『駭客松』或是『駭客爽』,其實總歸來說,就是讓開發人員盡情開發程式的活動。 這類活動的規則是,參加的開發者可以自由組隊,提交想法,然後當場實作。最後,在活動結束前,讓各隊伍一一上台展示成果。由於開發者的創意常常天馬行空,又能看到實際成果,所以這類活動都相當有意思。這次,OSDC.tw 提供了無限量供應的食物還有場地,活動時間是從當天早上 9:00 到下午 6:00,成果發表是從下午 4:30 開始,每個隊伍約有七個半小時實作自己的提案。 這次 Hackathon 活動,我與『魏藥』組隊,選的主題是『使用 JavaScript 打電話』,意即使用 JavaScript 開發出一支 Linux 應用程式,可以像手機一樣撥出電話並與對方通話。選這主題是因為我們的機器上剛好有 3G 數據卡(Modem),所以這個提案的目的,主要是撰寫一個 Node.js 模組『jsdx-ofono』,去提供控制 Modem 的 JavaScript API,讓開發者可以透過這組 APIs 撥打甚至是傳接 SMS/MMS 之類的訊息。最後,為了驗證並展示,運用了之前開發的『jsdx-toolkit』,用 JavaScript 撰寫了一個簡單的撥號介面『jsdx-app-voicecall』。 註:因為時間太趕,後來才發現,撥號 UI 忘了放倒退按鈕,所以撥錯號時要把程式重啟。:-P 如專案名,其主要整合了 oFone ,應用了之前開發的 node-dbus,所以省下了不少時間,最後再以 jsdx-toolkit 快速實作了一個 UI。原本希望,如果時間再充足一些,我們計劃幫 jsdx-ofono 加上 SMS/MMS 和讀寫 SIM 卡電話簿的功能,可惜最後沒來得及。 註:因為時間也不足,我們還來不及將 Linux 上的麥克風接上 oFone,所以目前接通後,只能聽到對方手機傳來的聲音。 此外,這次展示的兩個元件『jsdx-ofono』和『jsdx-app-voicecall』都有在 github 釋出,歡迎取用: https...

【OSDC.TW 2012】Let's Enjoy Node.js - All Development in JavaScript 簡報檔釋出

感謝各位捧場,上周六在『 OSDC.TW 2012 』所分享的『Let's Enjoy Node.js - All Development in JavaScript』,旨在介紹『 Node.js 』這新興的 Open Source 專案,我們可以預見,其將帶來軟體業相當重大的變革,並為 JavaScript 程式語言開拓了嶄新的局面。目前簡報檔釋出,歡迎各界取用和參閱。 自 2009 年 Node.js 公開發表以來,備受世界各地開發者囑目,在 2011 年 12 月更一度榮登 github 關注排行的第一位,超越了 Ruby on rails。Node.js 的出現意味著 JavaScript 語言從前端應用走進了 Server 的殿堂,除了效能表現不俗之外,使用其開發應用也相當迅速,未來 Web 開發者可以完全使用 JavaScript 語言打造網站服務,甚至是可大規模括展的雲端應用,堪稱 Web 開發者的夢想。 值得一提的是,Node.js 其實不僅限於 Web 應用,甚至可以用於各類系統程式開發,比較廣為人知的例子是 HP WebOS(前身是 Palm WebOS)。其採用了 Node.js ,做為系統服務的開發途徑之一。此外,Node.js 有模組化的設計,讓開發人員可以輕易使用各類其他語言(C/C++/Python... etc)為其擴充功能,彈性相當高,更讓 Node.js 不受限於任何開發領域。

【Node.js Taiwan 心得分享】How to Write Node.js Module 簡報檔釋出

於本週四所分享的『 Node.js Taiwan 社群聚會 - How to Write Node.js Module 心得分享 』,簡報檔經整理後釋出,對 Node.js Module 開發有興趣的人可以自行參閱。若有不瞭解之處,可與小弟聯絡和討論。如有發現問題,請不吝賜教。 本次分享主要有三大部份: 使用 JavaScript 開發 Node.js Module 學習使用 NPM 註冊帳號和上傳模組(Module)  進階議題:開發 Node.js 的 C/C++ Addon 簡報展示: 後記 由於小弟於 people.linux.org.tw 上的 SSH Key 遺失了,短期內沒空處理,所以無法像過去一樣直接上傳 PDF 供大家取用。因此,日後會使用 slideshare 來分享簡報。

各式 JavaScript Class 的效能比較

圖片
我們在做 JavaScript 開發時,常會使用到類別(Class) 的設計方法,但事實上,JavaScript 根本沒有所謂的類別(Class) 概念,此功能完全是靠動態物件(Object) 所模擬出來。因此,在 JavaScript 中,有數種方法可以定義和設計我們自己的類別(Class) 。可是哪一種方法的效能比較好呢?這便是本文的主題。 為免空口白話,筆者在 jsperf.com 建立了一個 Test Case『 Prototype Operator Performance 』以便實驗,並邀請各方網友使用瀏覽器前來測試,比較使用和未使用 Prototype 兩種情況,以及不同寫法的速度。(若你有興趣幫忙做實驗,進入該網站後, 請點選 Run Tests 開始測試) 註:在測試過程中,請確定你的瀏覽器,沒去跑其他的吃重的網頁,以確保實驗結果的準確性。 你可以在該網站上,觀察其他網友們的測試結果。但是,由於本次目的,主要測試的是同一種 JavaScript 引擎,處理不同建構方法的速度,所以,大家只要專注於在同一個瀏覽器下,其測試結果就可以。不同電腦,不同系統和不同瀏覽器的速度,並不是我們這次比較的重點。此外,因為 Node.js 使用的是 V8 JavaScript Engine,在本文中主要會拿 Chrome (因為 Chrome 使用的是 V8 JavaScript Engine)的結果討論。 這個測試有兩組實驗,第一組是測試呼叫類別(Class) 中方法(Method) 的速度,我們分別測試三種,用不同方法建構出來的類別(Class): 未使用原型(Prototype),直接在 Constructor 內定義 方法(Method) A = function() { this.message = function(s) { var msg = s + ''; }; this.addition = function(i, j) { return (i * 2 + j * 2) / 2; }; }; A_instance = new A(); A_instance.message('Hi'); A_instance.addition(i, 2); 使用原型(Prototype...

Node.js Taiwan 社群聚會 - How to Write Node.js Module 心得分享

無論你是否已經相當熟悉,還是想要嘗試入門 Node.js,應該都想要尋找興趣同好,找機會共同研究和分享彼此心得。已經辦了多次聚會和心得分享的『 Node.js Taiwan 社群 』,將於 4/12 (星期四)舉辦第五次的 Node.js 聚會,邀請廣大朋友們參加。 小弟有幸受邀,將於這次聚會交流心得分享,主題是『How to Write Node.js Module』。 在不久的文章『 我為什麼大舉投入 JavaScript 的相關開發 』內有提到,今天的 JavaScript 已經不再只是網頁前端的專利,除了能開發網站後端,也可以撰寫系統程式,甚至是嵌入式系統和跨平台的各類應用。而 Node.js 因為實作了許多基本的 JavaScript 函式庫,讓 JavaScript 可勝任許多的應用,所以近年來受到不少關注。此外,Node.js 的模組(Module)機制,更是讓我們能輕易擴充各種不同的功能,以及使用 C/C++ 為 Node.js 實作低階的 API。所以,想要完全不受限制的運用 JavaScript 開發各類應用,學會寫 Node.js Modules 是個必需要經歷的過程。 有鑑於此,本次的分享內容會提及: Node.js Ecosystem Pure JavaScript Module Development NPM(Node.js Package Manager) C/C++ Addon Development 若時間允許,會進一步探討 C/C++ Addon 所衍生的應用範例: System Programming in JavaScript Desktop Programming in JavaScript 詳細 Node.js Taiwan Party 聚會訊息如下: 官方公告: http://nodejs.tw/post/20631976641/nodeparty20120412 時間:2012/04/12 (星期四) 19:30 – 22:00 地點:台北市大安區金華街 122 號正對面 d.cafe 地下室 W-B05 室(創立方) (政治大學城區部,可從旁邊的小門直接進到地下室,找不到的人『 看圖 』) 有興趣的朋友們,歡迎前來參加,不吝指教。:-)

用 Node.js 實作多個 Process 監聽並處理同一個 Port

Node.js 實作了一個內建的模組『cluster』,目的在於提供開發者一個容易的方式,針對多核心機器進行支援。可惜的是,截至今天 Node.js v0.6.14 版本,『cluster』功能還是不夠完整,從官方文件上可以得知,其 API 仍處於實驗(Experimental)階段,在日後會有極大的變動(Drastic changes in future versions)。 而就 git repository 上最新的 Node.js 開發版本來看,『cluster』模組已經大幅度更改,也從簡單的 function call 變成了物件的設計。所以,目前非常不建議在自家產品中大量使用 『cluster』,至少短期內,他都不是穩定可用的,會有很大的改動空間。 不過,你如果是要實作 Web Service,會想要使用『cluster』的目的就顯而易見:『透過多個 Process 分擔流量和工作量』。若只是單單要做到這一點,我們可以自己來實作。 通常我們有兩種方式達成這個需求: 反向代理(Reverse Proxy) 技術 使用多個程序(Process) 監聽並處理同一個 Port 前者的做法,是建立一個常駐程式或機器,統一處理所有連線的需求,然後將這些連線做流量平衡(Load Balance),轉送並分配給後端多個程序或機器處理,待處理完成後,再將後端的回應送回給使用者。這樣的 Proxy 機制,你可以用已經相當成熟的解決方案達成,像是 Nginx 或 Apache。亦或是自己使用 Node.js 撰寫,但由於這不是本文的重點,日後再來討論這個實作的細節。 而後者,使用多個程序(Process) 監聽並處理同一個 Port,是本文的主題,也是『cluster』模組正在做的事。如果你有看過『cluster』的程式碼,就會發現它其實主要運用了兩個技術:『取得 net._handle』和『利用 process.send() 傳送 Handle 給子行程(child process)』。 知道了關鍵後,實作上就不是什麼大問題,主要流程是: 運用『net』建立一個 Server,目的在於監聽(listen) 80 Port 建立多個子行程(child process) 準備處理連線 將『net』的內建 Handle 傳給子行...

發佈 AppHouse-Manager 圖型化管理介面!

圖片
繼前文『 不靠別人!親手佈建自家的雲端服務平台 AppHouse 』所提到,我們以當今主流的雲端平台的佈建習慣為參考,開發了一個自己的 Hosting Platform,做為投入雲端產業的基礎建設。雖然與許多雲端業界的老前輩(如:Google、Amazon 等等)比起來,仍然不夠看,但研發仍逐步朝完整的解決方案前進。 在使用『 AppHouse 』時發現,網站應用程式的佈建雖然相當快速,但若是要直接在 AppHouse 上開發應用程式,會有相當多的麻煩,也不夠便捷。於是,撰寫並釋出了一套圖型化的管理程式『 AppHouse-Manager 』,用來管理 AppHouse 上所有的應用程式(Application)。 目前提供了功能,可以重啟特定的應用程式,讓開發者可以在撰寫和測試服務時,依自己的需要重新啟動自己的程式。 也實作了即時監控 Console ,我們可以透過瀏覽器即時偵錯(Debug)。 目前 AppHouse-Manager 還相當不足,只能說堪用而已,並還有許多欠缺改進的地方。不過,已經足夠讓工程師在 AppHouse 上進行開發工作。

不靠別人!親手佈建自家的雲端服務平台 AppHouse

現在,凡事只要扯上『雲端』兩字,價值就上漲好多倍,所以,任誰都想狹著『軟體奈米』之勢,大做文章。此外,在大多數人的印象中,雲端就是 Google App Engine(GAE) 、 Amazon E2 或 Microsoft Windows Azure 的代名詞,無論是誰,只要是能將服務放在上面,或是將公司搬到了台北 101 的 Google 樓上,就叫做上了雲端。而那些所謂專家說的 IaaS 、 PaaS 、 SaaS 專有名詞,其實都是舊瓶新酒,只是商業界幫雲端和網路生態的各個部份做了劃分,方便於解釋給投資人或政府單位的『難懂標題』而已。 簡單來說,雲端對一般的企業,最重要的是發展自家應用,提供更多的『加值』且『不需大量人力』的服務,然後對客戶進行『綁樁』;對中間維護伺服器的廠商,就是『租出更多的伺服器』,得到更『大規模的需求和機會』,進一步『降低機房建設和維護的成本』;而對電信單位,就是賣出更多『通信產品』和『頻寬線路』,也能換到更多『國家預算』。 雲端對不同的企業有不同的意義,但對終端的一般企業和使用者來說,建立一個不用擔心擴展性和極限的網路服務,是他的真正價值所在。所以講穿了,雲端並不是什麼新東西,多企業會將服務放在雲端上,求的不過就是為了量化的『擴展性(Scalability)』,如果你很熟悉網路產業,就會發現其實這就是以前,當一個網路服務長大到一定規模,才開始要考慮的事。只是現在這個時代,網路服務搭上了終端實體產品的『量產列車』,許多服務的第一時間規模就相當龐大,所以直接跳過網路服務的發展期,馬上得考量第二步的事。這也是為什麼現在雲端熱哄哄的原因。 假設業界使用雲端的真正原因,主要是為了追求擴展性,我們不能親手打造嗎?我們是否可以自己建構一個像 Google App Engine(GAE) 的平台,將自己的 Web App 輕鬆佈建在上面?也保留日後擴展的可能性? 於是『 AppHouse 』應運而生,我們開始投入開發這樣的專案,目前開放原始碼,以 GPL 做為授權而公開。雖然初期是自己使用為主,但這對在國內還未投入實際行動的雲端市場來說,算是一種相當特別的嘗試。如果可以,也希望能找到機會,在國內能建置公開的平台,供業界或軟體開發者使用。 『AppHouse』最終目標是提供一個 Hosting Platform,就如 Go...

使用 Node.js 控制網路連線管理員

既然以『國內首屈一指的 JavaScript 專家』為目標,使用 JavaScript 打造作業系統就是我們的終極目標。未來會將先前的 Flat Project(可參考舊文 Flat Project Demo - An OS for Tablets 平板作業系統 和 Flat Project - 從山寨做起,親手打造炫麗的平板系統 )以 JavaScript 重新架構,實作並提供一個更易於開發應用的環境。當然,就像過去所說,無論有多困難,產品化一直是我們的目標。 既然要開發作業系統,就要讓 JavaScript 能直接觸碰到系統層級或硬體裝置的控制,我們必須實作各種 JavaScript API 去達成這個目的,而前些日子所提及的『 node-dbus 』和『 jsdx-toolkit 』就是在做這類的工作。現在,基於 node-dbus,我們進一步和『 connman(Connection Manager) 』連接,實作出『 jsdx-connman 』,提供 JavaScript 網路管理機制的 API。這代表我們可以藉由 jsdx-connman 去控制無線、有線網路,甚至是WiMax、藍芽等各種連線介面。 如果想要嘗試 jsdx-connman,可以直接使用 NPM 安裝: npm install jsdx-connman 這邊有個範例,讓我們可以使用 jsdx-connman API 去得知無線裝置的狀態和掃描當前環境的 Wifi 無線基地台: var ConnMan = require('jsdx-connman'); var connman = new ConnMan(); connman.init(function() { if (connman.Wifi.Powered) console.log('Wifi is powered'); else console.log('Wifi is not powered'); if (connman.Wifi.Connected) console.log('Wifi is connected'); else console.log('Wifi is not connected'); ...

能處理 Binary Data 的 Node.js Buffer Class

從一開始 JavaScript 就被設計成易於處理 Unicode 的語言,其所有的動作,都無法直接操作 Binary 類型的資料。也就是說,JavaScript 對處裡一個個位元組(byte)的資料是沒輒的,因此使用範圍大幅受限。為了解決這個問題,Node.js另外設計了一個 Buffer class,讓開發者可以處理 Binary data。 為了方便理解,其實我們可以將 buffer class 看做為 C 語言中的 malloc(),使用它就像是和直接系統要一塊原始記憶體來使用。此外,因為 buffer class 被設計成在 V8 heap 之外配置記憶體,因此不受限於 V8 Engine heap 的 1.6GB 大小限制。 你可以用下列三種方式建立 Buffer 物件: /* 建立 16 Bytes 的記憶體空間 */ var buffer = new Buffer(16); /* 直接代入資料陣列 */ var buffer = new Buffer([ 8, 8, 6, 9, 2, 6, 3, 3, 3, 5, 7, 2, 1, 1, 1 ]); /* 直接代入字串 */ var buffer = new Buffer('String!', 'utf-8'); var buffer = new Buffer('String!', 'ascii'); 你可以寫入資料: var buffer = new Buffer(32); /* 寫入一段字串 */ buffer.write('Write something', 'utf-8'); /* 只寫入兩個字元 */ buffer.write('Write something', 2, 'ascii'); 以操作陣列(Array)的方法,單獨存取每個 Byte 的資料: var buffer = new Buffer(32); /* 將每個 byte 歸零 */ for (var i; i < buffer.length; i++) { buffer[i] = 0; } 當然也有像 memcpy() 的資料複製: var buffer1...