發表文章

目前顯示的是有「Web 相關技術」標籤的文章

打造自己的 Node.js Transform Stream

圖片
熟悉並學習實作 Node.js Stream,在 Node.js 開發者生涯裡是一件很重要的事,尤其在資料處理的工作上更是需要運用 Stream。在這些應該用的情境下,若不懂得使用 Stream,我們所開發出來的程式其執行效能及穩定性會相當令人擔心。 而如果你從未自己實作過 Stream,從 Transform Stream 開始入手是一個好選擇,也是一個非常實用的開發技巧。 更多關於 Stream 的說明,可以參閱 Node.js 官網上的文件: https://nodejs.org/api/stream.html 什麼是 Transform Stream? 你可能知道 Node.js 裡有多種 Stream 的機制,但其實主要是 ReadableStream 和 WritableStream 兩種基本 Stream 的組成和變化。而對一般開發者來說,最常自己實作的是 Transform Stream,你可以想像這是一個產品生產線上的加工器,進入 Transform Stream 的資料會被加工後輸出。 而以一個 Stream 而言,Transform Stream 同時具有 ReadableStream(讀入)和 WritableStream(輸出)的特性,俗話說「左耳進右耳出」就是其最佳的寫照。 舉一個 Node.js 官方的例子,利用 Gzip 的 Transform Stream 將通過的資料流進行壓縮: const zlib = require('zlib'); const gzip = zlib.createGzip(); const fs = require('fs'); const inp = fs.createReadStream('input.txt'); const out = fs.createWriteStream('input.txt.gz'); inp.pipe(gzip).pipe(out); 實作第一個 Transform Stream 先不必暸解太多 Stream 的專有名詞和機制,若想要實作一個標準的「耳邊風」Stream,程式碼如下: const Transform = require('stream...

Koa 2 起手式!

圖片
在 Node.js 的世界裡,說到今天最潮的 Web Framework,肯定就是 Koa!其用了最新的 JavaScript 語法和特性,來改善 Web Framework 的設計。只不過,Koa 雖然相對於其他舊的 Web Framework 來說有相當多的進步,但很多人卻相當討厭 Koa 的 Generator 設計,尤其是那些「*」符號,那不知所謂的 yield 也讓很多人不舒服。所以至今仍然有許多人在使用 express 來當作自己的 Web Framework,寧可繼續使用那老派的 callback 設計,而不肯嘗試 Koa。 隨著 ECMAScript 標準的進步,Koa 才剛被開發出來沒多久,原本的開發團隊就立即著手打造 Koa 2 ,開始更進一步採用更新的 JavaScript 特性,以 async/await 語法重新打造了全新且更簡潔的框架。可惜的是,由於 async/await 語法一直遲遲沒有被 JavaScript 引擎原生支援,因此總需要靠 babel 編譯打包程式碼後,才能正常跑在 Node.js 之上。這讓 Koa 2 一直無限期處於非穩定版,讓原開發者從開發的一開始,就打算等到 V8 和 Node.js 開始原生支援 async/await 後,才會被以穩定版(stable)的姿態釋出。 所以,即使 Koa 2 到了今天已經相當穩定,也開始有不少人使用在自己的線上服務,卻一直無限期處於非穩定版的狀態。 另外,由於 Koa 2 大量使用 Async/Await,如果你還對 Async/Await 的使用還不熟悉,建議在閱讀本文之前,先閱讀舊文「 JavaScript 好用的 async 異步函數! 」來學習如何使用。 學習 Koa 的好時機來囉 總算,日前 Node.js v7.6.0 釋出後已經正式宣布原生支援了 async/await 語法,而且不需要額外的參數選項。伴隨著這個消息,Koa 2.0 也隨即正式釋出了! Node.js 內建支援 ES7 的 async/await 真的是非常棒的消息!過去我們使用 async/await,都還需要 babel 的協助才能正常跑在舊版的 Node.js,不但開發上相當麻煩,非原生的各種 ES7 特性也浪費不少額外的記憶體和效能,這樣的問題在斤斤計較效...

上手使用 JavaScript 的 Map、Reduce 吧!

圖片
雖然有些概念類似甚至可以相通,但這裡並不是指常聽到的「MapReduce」,本文目的不是要討論如何運用 MapReduce 這樣的架構去處理大資料庫。這裡真正要討論的是,如何使用 JavaScript 裡陣列(Array)中的 .map() 和 .reduce() 方法,並把一些常見的使用方法和情境描述出來大家進行參考。 很多人對這兩個方法不習慣,原因不外乎是這兩種方法本來就不是一個非常直覺的東西,在大多數 JavaScript 語言的開發情境中,其實也沒有非得使用的理由。但不得不說,習慣了這兩個對陣列操作的方法,程式碼會變得簡潔,也更容易能處理一整批的資料。有時也能順便學習到一些「Functional Programming」會用到的概念,無論是在改善程式品質,還是投資自己的角度上,都有相當好處。 從最簡單的遍歷陣列開始 面對一個陣列裡的一堆資料,我們一定是從遍歷開始,一一處理裡面的每一筆資料。你也許已經非常熟悉如何遍歷陣列,最常見的不外乎就是兩種做法。 使用 for-loop: var myArr = [ 1, 2, 3 ]; for (var index in myArr) { console.log(myArr[index]); } 使用陣列內建的 forEach 方法: var myArr = [ 1, 2, 3 ]; myArr.forEach(function(element) { console.log(element); }); 使用 .map() 對每個陣列元素加工 有些時候,我們想對每個陣列元素(Element)進行加工處理,於是最土法煉鋼的方法大概就是這樣: 幫每個元素加一: var myArr = [ 1, 2, 3 ]; for (var index in myArr) { myArr[index] = myArr[index] + 1; } // [ 2, 3, 4 ] console.log(myArr); 這時你可以使用 .map() 方法來達成同樣目的: var myArr = [ 1, 2, 3 ]; var newArr = myArr.map(function(element) { return element + 1; }); // [...

JavaScript 好用的 async 異步函數!

圖片
先聲明,async 異步函數是 ECMAScript 第七版(ES7)才被支援的語法和特性,目前 ES7 還沒有被大多數的 JavaScript Engine 所實作,如果你要使用,需要用到 babel 這類工具,先把此程式編譯轉換,讓其可在舊版本 JavaScript Engine 上執行。 如果你覺得以 co 模組來操作 Generator 很好用,你可以想像 async 異步函數就是原生的 co,幾乎是同樣的使用方式,同樣的使用概念,只不過不再需要使用 generator 和 yield 這類語法。如果你是個過不了在函數上有個醜陋「*」符號這一關的人,async 異步函數的使用方式應該會讓你感覺到舒服許多。 什麼是 async 異步函數(async functions)? 異步函數使用方式其實和一般的函數一樣,只不過在這函數之內的程式,可以用 await 的語法去執行並等待異步工作(如:Promise)而不需要使用到骯髒的 callback function。宣告並使用一個 async 異步函數,就是在定義函數時加上「async」,然後直接執行這個函數即可,簡單的範例如下: async function myAsyncFunc() { console.log('Hello async functions!'); } myAsyncFunc(); 搭配 Promise 的使用 Promise 通常被大量用來管理非同步的工作,並讓開發者容易管理錯誤拋出等機制,一個典型的 Promise 使用如下: var task = new Promise(function(resolve, reject) { // 執行一個非同步的工作,完成後呼叫帶入的 callback doAsyncTask(function(err) { // 有問題呼叫 reject,並帶入錯誤值 if (err) return reject(err); // 成功呼叫 resolve 並帶入回傳值 resolve('VALUE'); }); }); // 使用 then 去執行並等待工作完成,成功會呼叫 callba...

下一代的框架:Koa 1.0 起手式

圖片
身為 Node.js 使用者的你,還在使用 Express 嗎?快來使用下一代的 Web Framework 吧!Koa 是由 Express 的開發者們出來所開發的新網站框架,嘗試採用了最新的 ECMAScript 6 語法,讓開發者可以用更簡約的方式,開發網站應用程式,讓程式碼更好維護之外,也能受益於最新的語言特性。 穩定版與不穩定版 現在的 Koa 分為 1.0 和 2.0 兩個版本,1.0 使用 ES6 的 Generator 特性,也是目前的 stable 版本,而 2.0 採用 ES7+ 的 async/await,據 Koa 官方說法,2.0 穩定度可以用於實際產品,只是在 ECMAScript 7 規格正式敲定,且 JavaScript V8 Engine 推出原生的實作之前,將無限期處於 unstable 的狀態。也就是說,若你想要在你自己的專案上使用 2.0,你必須使用 babel 這一類的編譯器,因為裡面用到了 ES7 的語法。 本篇文章的重點將放在 Koa 1.0 之上,畢竟在 ECMAScript 7 還處於草案階段的現在,很難說未來會不會有什麼改變。 安裝 Koa 由於 Koa 需要用到 ECMAScript 6 的語言特性,請先檢查你的 Node.js 版本,最少為 0.12 以上,如果你已經使用了 Node.js 4.0 或更高版本,請不用擔心這個問題。 然後透過 NPM 即可安裝模組: npm install koa 開發第一個應用程式 開發 Koa 應用程式非常容易,下面是程式碼範例: var koa = require('koa'); var app = koa(); app.use(function *() { this.body = 'Hello World'; }); app.listen(3001); 跑起來後,用瀏覽器連入 3001 埠即可看到「Hello World」的字樣,因為 this.body 的內容,將會被輸出到前端瀏覽器上。 使用 Generator 打造的 Middleware koa.use() 將用來載入 Middleware,所有連線工作都會經過 Middleware 處理。所以前一個例子裡,我們...

Lantern 專案:快速打造屬於自己的 Isomorphic 網站服務

圖片
話說,Isomorphic 一直是 Node.js 開發者的夢想,期望同一套程式碼前後端都可以使用,大幅簡化程式碼和加速開發。此外,動態網頁的 SEO 問題也可以同時獲得解決,許多效能問題也可以得到改善。但是,要實現 Isomorphic 的架構,有很多的問題得先解決,會花大量時間在前期工作上,往往讓許多開發者頭痛。 儘管頭痛,仍然阻止不了大家往 Isomorphic 的世界前進,我也因此建立了一個專案「 Lantern 」,希望能讓更多人能以 Isomorphic 架構,快速建構出自己的網站服務,省去許多前期工作的時間。該專案是一個網站服務的樣板,實作了會員系統、權限管理、第三方登入、多國語系和送信機制等功能,在使用者介面上也做了一個還算美觀的介面。基本上,開發者只要 clone 下來,然後修改設定檔或改改介面、增加點功能,就可以快速完成一個屬於自己的全新網站服務。 最特別的是,「 Lantern 」整合了現今所有最新的技術和概念,包括了 Koa、React、FLUX、ES6/7+、Webpack 以及 Semantic UI,大量運用了 Generator、class 及 decorator 等最新 JavaScript 語言特性來簡化設計。所以,如果你想要接觸最新的技術,完全可以透過修改「 Lantern 」專案來學習和熟悉。 目前「 Lantern 」支援 Facebook 剛發佈的最新 React v0.14+ 和 react-router 1.0.0+,也避免使用像 redux 這類反 FLUX 原始設計的框架,讓原本熟悉 React 和 FLUX 架構的開發者,可以快速上手。也提供一些常見的 Extension,方便開發者寫出前後端通用的程式碼,大多數情況下,開發者不需思考程式碼運行在前端還是後端。 快速安裝使用 若想要使用「Lantern」,方式很簡單,先從 Github 取得程式碼: git clone git@github.com:cfsghost/lantern.git 安裝必要之 NPM 模組: npm install 使用 webpack 編譯專案(若要正式上線,可加上 -p 選項來編譯): webpack 運行網站服務: node app.js 最後可以使用瀏覽器開啟網址,確認是否成功: http://...

Node.js 的單執行緒(Single Thread)設計,到底有什麼優點?

圖片
這是個總有人一問再問的問題,到底 Node.js 這樣單執行緒(Single Thread)的設計,到底有什麼優點?為什麼總是有人說,它比傳統多執行緒的設計來得有效率?以往,一旦開始討論這個問題,總是會有人開始提到 Context Switch、Asynchronous 等機制,越講越玄也越講越複雜化。 其實我們可以用簡單的餐廳比喻,就能理解 Single Thread 加上事件驅動(Event-driven)的機制,如何與傳統設計不一樣。 場景想像 試想一個場景:一間餐廳有 100 個座位,然後來了100個客人。 處理方法 身為老闆的你,你會選擇哪種方式服務這些客人: 請100個服務生一對一服務這些客人。 請 25 個服務生,看當下狀況服務這些客人。 一般來說,傳統的多 Multi-thread 的設計就類似方法 1,而 Single-thread 且 Event-driven 的設計就是方法 2。 通常大多數情況我們會選擇方法 2,因為客人通常都是處於等待(看菜單、等上菜、吃自己)的情況,並不需要服務生貼身服務。所以即便請 100 個服務生,這些服務生大多數時間也只是等在那也佔地方,而服務生眾多也導致服務生之間的溝通和互動其實不易,更不容易交換資源,回報和協同工作難以進行。反而安排一個小型的外場班,讓裡面的人合作見機行事,會比派出 100 個各自獨立的人來得好。 併發數高的原因 併發數(concurrent request)指的是單位時間內可以處理的要求量,一般用來評估一個網路應用程式的效能。而通常在網路服務裡,併發數也相當於單一時間內能服務的連線數量。 所以,以前面餐廳外場班的模型來說,如果你有 100 個服務生,就可以服務 400 個客人。換句話說,同樣的資源,能處理的併發數(concurrent requests)也就比較高。 後記 不過如果你開的是酒店或按摩店,那可能就要請一百位服務生了。:-)

快樂玩 ES6 Generator,從 co 起手式開始

圖片
自從 Node.js 0.12 版和 io.js 之後,大量的開發者開始了各自的 ECMAScript 6 大冒險,許多人對 Generator 的使用仍跌跌撞撞,對於這種看似「同步(Synchronous)」的「異步(Asynchronous)」機制,有許多人腦袋遲遲無法轉過來。雖然在小弟的書(參閱連結: 新書報到!Node.js 模組參考手冊! )已經有清楚的說明 Generator 使用方法,但就許多讀者回函來看,對於 JavaScript 越是熟悉的人,越無法直觀理解 Generator 的思維,甚至是老是抓不准使用的時機點。 尤其是過去我們已經有 Promise、async、Q 和 bluebird 等處理非同步程式流程的模組和工具,很多人就是覺得沒有使用 Generator 的必要。不過,如果你會使用 co 模組,你會突然發現若是將過去的流程機制與 Generator 相搭配,程式開發將變得更為流暢。 若想要安裝 co 模組,可以直接以 NPM 下載: npm install co 本文接下來會說明一些 co 的基本使用,破除一些 Generator 難以使用的地方,讓開發者們更容易開始 Generator 的旅程。 讓原生 Generator 更好用 這是很多人不喜歡使用 Generator 的主因,以往為了使用 Generator,我們還要先建立一個 Generator 的函數,然後不時的去處理 Generator 所返回的資訊,一遍又一遍進入 Generator 之中。因此,無論 Generator 再好用,這些麻煩的動作也完全抵銷他的優勢,大多數人還不如回到舊的流程控制方法,以免徒增自己的麻煩。 而如果使用 co,可以直接將 Generator 函數當作「立即函數使用」,其餘的部份我們可以不需要擔心: var co = require('co'); co(function *() {     console.log('Inside'); }) 再也不用煩惱 yield! 以前光是 Promise,就已經讓很多人詬病,覺得每次使用 Promise 都要花許多時間對函數進行包裝,而 Generator 也有類似的問題,若是要使用 yield,更是一件大工程。於是,co ...

JavaScript 的各種迷霧

圖片
 在 Facebook 看到很多人都在整理自己的程式筆記,我也整理關於 JavaScript 語言常被誤解部份的筆記,然後分享出來供各位同好參考。 講實話,從 1995 年開始的 JavaScript,直到前幾年,都讓我恨的牙癢癢,甚至覺得他是個垃圾,因為當時的他太沒有規範,效能極差。直到近年來才逐步改善,我也才慢慢擺脫對他的排斥及恨意。 但就算已經有標準規範,JavaScript 語言對很多人來說依然很頭痛,除了其 Asynchronous 非同步的機制外,更要面對其極為動態(Dynamic)的特性,而從 OOP 的角度來看,其 classless 的設計更讓人不知所措(ES6 之後開始支援 Class),與傳統的 OOP 相去甚遠。所以,JavaScript 處處與其他語言完全不一樣的概念及思維,讓很多人在裡面處處誤解。 所以若是想學習 JavaScript 深入的概念,最好的方式就是放下其他語言的既有概念,直接了解 JavaScript 的核心機制,雖然會讓人手足無措,但卻是最好的手段。否則,很容易練就或死背很多怪招,寫出難以除錯或過於複雜的程式碼,當然,更嚴重的是誤導他人。 要深入或精通 JavaScript,務必了解並思考其執行程式時發生什麼事,每一行程式碼當下被執行時的狀態,遠遠比程式碼排列來得重要。只要掌握每一行程式碼的『執 行當下』,所有 JavaScript 的疑難雜症,都能迎刃而解。關於這一點,有興趣閱讀硬梆梆定義文件的,可以參考 ECMA-626 的『10.3 Execution Contexts』一節。(參考網址: http://www.ecma-international.org/ecma-262/5.1/#sec-10.3 ) 關於 this 關鍵字的機制 很多人會搞糊塗 this 關鍵字,就因為他是一個會被 Execution Contexts 大量影響的東西。JavaScript 在 Function 或 Context 被執行時,才會依當下情況去決定 this 為何。這代表,使用 this 時在哪一個 function 或地方不重要,而是當進入這個使用 this 的 context 時(如:Function 被執行時)才會決定 this 是什麼,this 是什麼只跟你如...

新書報到!Node.js 模組參考手冊!

圖片
經過幾個月努力,新書『 Node.js 模組參考手冊 』終於誕生。這本新書與前一本『不一樣的 Node.js』稍稍不同,主要訴求不是初學者入門,而是參考用書,無論是新手還是已經很熟練 Node.js 的專家好手,都可以拿來參考,還希望各界多多支持! 有鑑於 Node.js 發展迅速,其應用已經不只是被侷限在 Web 之上,甚至適合各種不同的領域與場景。所以,許多的功能及模組被大量開發出來,從網路應用、桌面應用甚至到嵌入式應用都可以使用 Node.js 來開發。 可以應用在各種場景,代表就會有不少人面對 Node.js 數不清的模組時,總是不知道該怎麼辦,除了很難抉擇之外,更是有很多超出原本常識的模組存在。有些時候,更是需要將許多模組拼湊起來,才能完成一個特殊的功能。 然而,大量的應用範例,也需要花大量時間才能一一摸索,若不是有人事先整理好,對於大多數人來說,無疑是永遠無緣觸碰。因此,這本書為此而生,希望透過大量整理各種應用範例,以減少 Node.js 開發者摸索的時間,加速學習或研究的速度,更甚至縮短產品開發的週期。 如果你是初學者,你可以從中找到一些基本模組的完整範例參考,或是學習模組選擇的方法。如果你已經是很熟悉 Node.js 開發的專家,你可以從本書看到許多使用 Node.js 所開發的特異功能的應用範例,如:Bittorrent、SSH Server、演算法、加密、文件格式、多媒體支援等。此外,本書也將提及 C/C++ 原生模組和 V8 JavaScript 引擎的原理和範例,還有各種資料庫、Message Queue(訊息佇列)等常用的完整使用範例,當然也有今年最新的 io.js 相關內容。 雖然說本書名為模組參考手冊,但整本書卻是以應用範例為導向,並非完全是一個個模組的介紹,有很多是多個模組整合而成的範例,許多部份都是網路上連原文文件都缺少的資訊或文獻,可以說是花大量時間和經驗的結晶。 我只能說,希望讀者們會喜歡!希望能幫上大家工作開發上的忙!請大家多多支持! 後記 前一本『不一樣的 Node.js』,因為一些模組更新太快,所以有些章節已經有些老舊,如果你是前一本書的讀者,可以和新書『 Node.js 模組參考手冊 』做比對參考,因為裡面有雷同的章節,可以使用新書的方法來取代舊書老舊的部份。 至於舊書翻版,我們已...

io.js 的 ES6 Collection 支援 - Set

io.js 不做任何設定下,預設支援了一些 ECMAScript 6 的語法,其中包括一系列的 Collection 支援,這讓 JavaScript 在資料操作上多了一些方便之處。本文將討論到的 Set 物件,就是其中一個 Collection 類別。 簡單來說,Set 是一個類似 Array 的物件型態,可以用於處理有序的資料,而且內建迭代器(Iterator:在某些應用上同樣功能也會稱之游標 Cursor),讓開發者可以很容易對資料進行一筆筆的處理。 基本操作 基本的 Set 物件使用很簡單,如下所示: // 建立一個新的 Set var items = new Set(); // 依序加入資料 items.add('Fred'); items.add('Stacy'); items.add('Wesley'); items.add('Rance'); items.add('Kevin'); items.add('Alex'); // 依序印出 Set 物件內的所有資料 for (var item of items) {     console.log(item); } 比較特別的是,如果要依序印出 Set 物件內的所有資料,需要使用『of』這個關鍵字。原因是 Set 物件本身是一個 Generator 實作所致,如果我們想要一次把 Generator 內的工作跑完,需要運用 for-loop 加上 of 關鍵字來達成。 註:關於 Generator 與 of 關鍵字,日後有空再撰文說明其細節。總之,只要記得必須使用 of 關鍵字才能一一讀取 Set 物件內的資料,就像 Array 的 for-loop 加上 in 關鍵字。 刪除資料 刪除特定資料可以使用 remove() 方法來達成,如下所示: items.remove('Wesley'); 若是要清空資料,可以使用 clear() 方法: items.clear(); 檢查資料是否存在 我們可以直接利用 has() 方法檢查特定資料是否存在: items.has('Rance'); 迭代器(Iterator)的使用 Set 的迭代器是圍繞著 Generato...

Koa 的非同步流程設計

Koa 採用了 Generator 來控制非同步流程,所以在採用 Koa 的程式碼上,我們會看到很多 yield 關鍵字的出現。某程度來說,Generator 讓程式碼變得乾淨許多,也平坦許多,比較少出現太複雜的 Callback 高山。這對 JavaScript 來說是件不錯的事,只是,對很多開發者來說,需要點時間熟悉其概念。 總而言之,所有 yield 的關鍵字,一定只會出現在 Generator 當中,而一個 Generator 長得會是一個以『*』符號開頭的函數模樣: function *() {     // 工作流程 } 所以若是你仔細觀察,就會發現 Koa 的路由處理,採用的不是 callback 來處理客戶端要求,而是 Generator: router.get('/test', function *() {     // 處理客戶端要求的工作 }); 其實不久前,舊文『 如何於 KOA 實作長輪詢(LONG-POLLING)機制 』已提及怎麼來掌控 Koa 的流程,雖然只是簡單提及,但已經大略展示其使用方法。簡單來說,你可以當作這個 Generator 結束後,與客戶端的連線就會結束,所以我們如果要處理非同步的工作,也必須避免和阻止這個 Generator 執行完。 使用 yield 控制 Generator 的流程 為了阻止 Generator 一下就跑完,我們會使用 yield 方法來暫停 Generator 的執行,並等待一個需要花時間的非同步工作完成。如果你對舊文的內容有印象就會知道,想要使用 yield 在 Koa 中去呼叫一個非同步機制,就需要設計一個特別的函數,其函數有一個 callback,當這個 callback 被呼叫時,代表工作完成。 如下面範例就是想要執行一個非同步函數 setTimeout(),並等待其執行完成。在這範例中,我們加上了 console.log() 印出 START 和 END 字串,便於觀察其行為: router.get('/test', function *() {     console.log('START');     // 暫停 Generator 並等待工作完成     y...

【Node.js 小密技】使用 crypto 模組亂數產生字串

已非常熟悉 Node.js 的人都知道,crypto 模組是一個無中生有的神器。我們可以用它的 API 加工加密資料,也可以解開加密後的包裹。既然和密碼處理相關,當然也有亂數產生器,可供開發者產生一大堆的亂數資料。 如果你需要一個 32Bytes 長度的亂數資料,可以直接呼叫 crypto.randomBytes() 並帶入長度後生成: var crypto = require('crypto'); var buf = crypto.randomBytes(32); 註:回傳的結果 buf ,是一個 binary buffer,而每一個 Bytes 都會是範圍在 0 ~ 255 (0x00 ~ 0xff)的數字。 不過,在多數應用中,我們更常需要一個亂數字串,而非二進位的亂數資料,這時就需要做一些進一步的加工處理。方法其實不只一種,如建表、取代不可見字元碼等方式都可以,沒有標準做法。但懶惰的開發者們,多半是直接利用 Buffer 內建的 API 來將資料轉換成字串,並指定編碼方式來達成。 下面兩種方法都可行: buf.toString('hex'); buf.toString('base64'); 只是,使用十六進位(hex),會讓你的最後的字串單純只有 0-9 和 a-f 的字元存在,所以使用 base64 是比較好的選擇,讓字串多變並複雜些。 註:base64 編碼是以 6 bits 為單位來進行處理,而 1 Byte 有 8bits。如果你的資料長度非 6 bits 的整數倍長度,base64 會在結尾補上『=』。有些人覺得多了一些『=』符號很醜,就會用 replace() 替代掉或者是一開始就取 6 bits 整數倍長度的亂數資料(如:3 bytes、6 bytes 等等)。 有些情況,我們需要特定長度的亂數字串,也可以搭配使用 substr(),只是要確定生成的字串長度,比我們想要的字串長度還要長。下面的範例,就是取八個字元長度的字串: buf.toString('base64').substr(0, 8); 當然,若你想要一次搞定,也可以將之前所說的,全部串在一起寫: var randomString = crypto.randomBytes(32).toSt...

Express 4 來了!好用的 Router 機制

還記得前陣子,就在書將出版之際,半路殺出來最新的 Express 4,使得筆者手忙腳亂,緊急通知出版社修改書的內容。將所有使用到 Express 的範例,都特別加上版本號的指定,讓讀者在照著範例做時,能夠使用舊的 Express 3.0,而不會發生任何問題。最新的 Express 4 雖然效能提升不少,也有一些好用的新東西,但和舊版有些微 API 的不相容,此外,也因為是新東西,可能很多東西的支援會發生問題,如果舊版本在上線的產品中運行相當穩定,建議先不要急著升級。 Express 4 做了一些改進,有不少新東西,其中相當值得提的一項就是路由機制(Router)的翻新。如果你以前在使用 Node.js + Express 開發網站服務時,因為 Router 很難管理而痛苦不已,這將是一個你會愛上的功能改進。 傳統的使用方法 傳統的 Router 設定方法依然可以運作,我們可以放心使用。 var express = require('express'); // Create express application var app = express(); // Apply this router on (/apis/user) app.get('/', function(req, res) {     // Home }); app.listen(8000); 新 Router 物件的使用方法範例 除了舊的方法之外,你可以用 Router() 去建立一個 Express 的 Router 物件,然後管理你一系列的路由規則。 var express = require('express'); // Create express application var app = express(); // Create a router to handle routes for a set of  user API var userAPI = express.Router(); // Sign in (/apis/user/signin) userAPI.post('/signin', function(req, res) {     // ... }); // Sign out (...

Feature-oriented Programming with Node.js

Feature-oriented Programming(FOP)這個名詞對很多人來說應該相當陌生,這是一個鮮少人討論的開發模式,尋找了一下,也找不太到中文的說明和翻譯,所以我就暫時稱它為『特色導向程式開發』。如果你有興趣,可以去搜尋它,或使用關鍵字『Feature-oriented Software Development』找到更多資源。也有一個以 FOP 概念所改良的 C++ 語言『FeatureC++』,可以參考。 因為筆者眼前專注於 Node.js 的發展,所以也用 Node.js 實作了一非常個簡單的 Framework 『wag.js』,讓我們可以在 JavaScript 語言的環境下,引用 FOP 的開發概念來設計軟體。你可以用 npm 直接安裝他: npm install wag.js 之所以會一時興起研究 FOP,是因為多年以來,一直為了重覆開發所苦,很多相同的東西一直不停重覆做了又做,總覺得自己一直在浪費時間,所以想試著尋找個方法來改善眼前的窘境。最麻煩的問題在於,雖然早就應用了許多模組化方法,我們也能把很多功能事先做好打包好,但仍然像個有數不清節點的連連看遊戲,讓人花不少時間在上面編織程式軟體。重點是,當其中有絕大多數的過程是一樣的時候,總讓人做得很無力。 你可以想一想,當你想要寫一個新的專案時,你通常最大的阻力是什麼?又有多少繁雜的事,每次開新專案時都重覆在做?而最令人煩燥的是,因為專案類型的不同,有些微的差異,所以難以用一個標準自動化的方式去完成。 這也是一般人和工程師最大的差別,甚至是造成溝通不良。一般人總是想著是我要什麼功能、再增加哪些功能;工程師則是一直在想著,我要挑選使用哪些功能模組,又該怎麼從數不清的可能中,選一個可行的方法組裝他們?如果想成捏黏土來比喻,一般人會捏個大概形狀,再往上慢慢堆想要的東西,慢慢趨近成果,而工程師會捏好各個部位,再把他一一拼湊起來。 我想,當你能回憶起客戶或老闆跟你說:『這功能很簡單,你應該能馬上做好』,你應該就能更明白我所說的,一般人與工程師的思維差異。不過,事實上,工程師思維和一般人沒兩樣,也是把東西堆起來,只是,工程師所設計出來的各種部位的元件,總是很難拼湊在一起,必需要花些功夫。 到底,有沒有什麼辦法,可以減少各種元件和功能模組的拼湊困難呢?讓我們可以更專心的做一個有更多...

不一樣的 Node.js!終於完成的新書前來報到!

圖片
這陣子,最怕的就是有人問:『書什麼時候要發行?』,參加社群聚會或活動時,有人會問我,平常周圍朋友也會問我,工作上隊友和客戶都會問我,只有一些親人根本不知道不知道我在寫書,所以不會問我。如果你問我,寫書這件事上,你最怕的是什麼?我會跟你說,出版社截稿日期的死線(Deadline)並不是最可怕的,最可怕的是,它是一種詛咒,讓周圍人都會特別關心你的一種魔法。而這個關心的壓力,讓人喘不過氣來。 還好,書總算從初稿、校稿到排版完成,直到出版社編輯傳來最後的封面設計,才讓人鬆了一口氣。可以告訴大家,書總算要真正出來了! 事實上,國內 Node.js 的書其實並不多,其中幾乎多為翻譯書,或是從簡體直接翻成繁體中文的書。這讓這幾年一直在到處推廣 Node.js 的我,相當困擾。每當有人問起 Node.js 有什麼書可以看時,我總是無法推薦出很多本給大家參考。所以,當出版社的編輯跟我說,希望寫一本 Node.js 的中文書時,我其實相當開心。 還記得當時接下這個任務後,我便開始思考和回想,在推廣和使用 Node.js 時,所遭遇到的困難是什麼?我能否藉這本書來幫助讀者排除這些困難?甚至給讀者一個更大的視野,一個 Node.js 可以發揮在各種領域的可能性。 此外,網路時代來臨後,有太多的新資料都可以從網路上取得,這本書要提供什麼內容,更是需要被探討的問題。尤其是 Node.js 這樣版本號快速上升的新技術,可能書還沒寫完,內容就已經過時。在種種思索下,期望本書的定位,將帶給大家的不是絕對的技術新知,而是一本學習 Node.js 的參考書和技術指南,讓想入門的讀者可以學會怎麼使用 Node.js,讓已經懂的人可以知道 Node.js 還能做些什麼不一樣的事,更進一步知道從哪裡去得到更多 Node.js 的新知。如果這本書在幾年後,仍有六成的資料值得參考,那就算完美達成我賦予它的任務了。 從引領初學者的角度來看,並參考了一些市上的 Node.js 書籍,也從過去教育訓練和推廣的場合發現一個現象。Node.js 不是什麼很難的新東西,如果有人已經很熟悉 JavaScript 語言,而且能寫的很好,Node.js 根本是小菜一碟。所以,多半不得其門而入的人,是對 JavaScript 不這麼熟悉,或是想使用 Node.js 技術進行第一次接觸程式開發的人。只不過,...

Web 技術中的 Session 是什麼?

圖片
很久沒更新了,自從十二月底退伍之後,一直忙著將書完稿給出版社,沒空坐下來好好在 Blog 上寫點東西。沒辦法,在當兵時閒不下來,就答應了出版社的邀約開始寫 Node.js 的書,因此欠下了書的債。還好,如預期的寫完了,預計這一兩個月應該就會上市,還請各界多多捧場! 會寫這篇文章的原故,是因為在 Facebook 的社群上,有人問起了關於 Session 和 Cookie 相關性的問題。其實,社群的人都很好,有許多熱心的網友願意幫助別人。不過,為了幫忙回答問題,大家七嘴八舌的東說一句西說一句,甚至引起莫明的論戰,實在不是一個好的現象。況且,使用不同語言、有不同技術背景的人,都各自用自己的角度去描述和解說,讓原本就已經不懂的人更有如瞎子摸象,見不到全貌,搞更糊塗了。對發問的人來說,也不知該聽誰的好。 說來湊巧,筆者剛好在剛截稿的 Node.js 書籍中,對 Session 概念也有許多著墨。所以之前稍微在網路上查過,發現鮮少有人提出對 Session 技術的完整說明,而多半是討論 ASP、.Net、Java、PHP 等語言或框架中如何使用 Session,以及一些延伸的特性,以致很多人對 Session 的概念相當片面。因此這次的事件後,一些網友也建議我把在 Facebook 上回應的完整內容,在 Blog 發表記錄下來,讓更多人對 Session 有個比較完整且正確的認識。 本文目標 在 Web 的世界裡,Session 已經是被廣泛使用的一種技術,大多數的 Web 開發者,肯定都能運用自如。在現今的各類 Web 應用程式的開發框架和工具中,Session 也已經被包裝成容易使用的模式,所以本文也就不再多討論 Session 怎麼去使用,而是著重在 Session 的原理和實現上。要知道,無論是使用哪一種語言,這 Session 概念上都是通用的,沒有什麼不一樣。 Session 是什麼? Session 之所以會存在,是因為 HTTP 為 stateless 的設計,Server 和 Client 不會一直保持連線狀態,也不會有雙方狀態的即時更新,所以,Server 並不知道 Client 的狀態(像是是否已經登入)。因此,後來的網站開發者,採用 Session 這樣的設計來解決這問題。有趣的是,Se...

COSCUP 2013 is coming!

今年 COSCUP 很有錢、很盛大,整個活動從中研院移師到了台北國際會議廳,議程多達八軌。很難想像三四年前,自己幫忙 COSCUP 辦活動時的情景,和今天相較之下,當年的活動實在迷你,大家都希望哪一天能殺入台北國際會議廳。沒想到,COSCUP 靠後起之秀多年來的努力,真的在今年達成所有人的願望!我們真的要為這些工作人員和總召柏強喝采!謝謝他們每年不辭辛勞的貢獻! 慚愧的是,COSCUP 長越大,更顯得我小小的講者的微不足道,如今我唯一能貢獻的,大概就只剩對 Open Source 的熱情。因此,自去年在 COSCUP 2012 的國際舞台『發表退學宣言』後,這個大學讀了七年還是沒畢業的我,今年仍厚著臉皮投了稿,稿也被入取。這邊非常感謝議程審核人員的親睞,讓我贏得今年的一段宣言時間,還有開賣一分鐘內就沒有的入場門票。 :-) 至於我這次要講的主題是:『我用 Node.js 開發自己的 Web 瀏覽器?』 時間地點是:COSCUP 2013 第二天(8/4) 10:00,101CD 場。 其實,正當投稿截止之際,當時熱映的『鋼鐵人3』給我了很大的啟示。不禁思考,身為工程師的我們,是否已經被工具和自己曾經所創造的東西所束縛了?如果我們今天把眼前的電腦給砸了,是否全身上下功力全失?無法有任何作為? 這樣的概念,套在 JavaScript 這個近年來很夯的語言上,更是貼切不過。對很多人而言,失去瀏覽器為依靠的 JavaScript,令人感到不安、充滿焦慮,好像就不知道能用 JavaScript 做什麼事了。所以,為了破除迷思,就面對他吧!這是一個小小的實驗,讓我們嘗試用 JavaScript(Node.js) 打造自己的網頁瀏覽器,支援 HTML5/CSS3/WebGL 等最新標準的瀏覽器! 如果你至今還是無法完全明白 Node.js 的能耐,期待與你見面交流。

JSDC 2013 簡報釋出!NPK 與 JavaScript OS (Stem) 登場!

最近比較忙,一直拖到現在,才有點時間上傳我在今年 JSDC 的簡報。這次,給的講題是『我編譯故我在:誰說 Node.js 程式不能編成 Binary』,主要探討怎麼使用 NPK 打包你寫的 Node.js 程式,以及把 JavaScript 程式碼編譯成二進位(Binary)檔,甚至是進一步的加密設計。NPK 雖然還只是初版,目前支援了三種博君一笑的封裝等級:卸妝(Remove mock-up)、媽媽不認識(Mom doesn't recognize)、爸爸不認識(Dad doesn't recognize),有興趣了解這三種等級不同的人,可以參考我的簡報: 當然,參加這種活動需要的是熱血,不在 Lightening Talk 閃電秀登場一下怎麼可以呢?於是當天毫不考慮的搶了一個名額,用短短的五分鐘介紹 Mandice 團隊最近在做的 JavaScript OS - 『 Stem 』。在 Stem 的平台之下,無論你是否為嵌入式系統或作業系統的高手,只需要懂 JavaScript 和純粹的 Web 相關技術,你就可以開發自己的嵌入式應用,或讓你的舊電腦或開發板有全新的用途。 後記 大家都知道,做外包工作,一向很難累積東西,唯一能累積的,就是設計工具以加速自己做案子的速度。因此,Stem OS 就是我們經歷過許多的案子後,自己設計的平台,讓我們可以盡可能完全用 JavaScript 快速開發嵌入式系統,然後結合硬體開發設計各式應用。在 Stem 裡,只需要懂 JavaScript 和 Web 相關技術,就能勝任開發工作,實現你心中的 Idea。如果說 3D Printer 是可以讓你快速打造模型實體,那 Stem OS,就是能將你心中的 Idea,化為空硬體的靈魂,Idea 的 3D Printer。 這對創業者、創新者和非資訊產業的公司來說,都是一個可以快速切入設計產品和自家工具的機會,不妨嘗試看看。:-) 如果有任何需求,無論是顧問、教育訓練還是合作開發,都歡迎與我們 Mandice 聯絡,或來信到 fred@mandice.com。

NPK 釋出!打包你的 Node.js 程式!

『 NPK 』是什麼?一個打包 Node.js 程式的工具,之所以會有這個工具,完全是拜下周(5/18 - 5/19)將在中研院舉行的 JSDC 所賜。因為這次筆者也有個 Talk,將探討如何去編譯我們寫出來的 Node.js 程式,所以過程中便寫出了這樣一個工具。 https://github.com/cfsghost/npk 事實上,目前的 NPK 不是個新東西。JavaScript 經過多年的發展,早已經有非常多合併 JavaScript 程式碼的工具可以使用,對於前端工程師來說,是再尋常不過。不過,針對 Node.js 的程式碼,這樣的工具卻相對來說非常少。 如果你想嘗試使用看看,可以立即用 NPM 來安裝 NPK: npm install npk -g 以 NPK 裡的範例專案為例,你可以直接下命令打包該專案: npk tests/purejs/ 接著你可以在輸出的資料夾中找到打包好的檔案: tests/purejs/out/app.js/ 甚至是直接執行他: node tests/purejs/out/app.js/app.js NPK 工具定義了一個新的屬性『npk_target』在 package.json,用來讓程式人員自行決定要合併和連結哪些 JavaScript 程式(像過去為 C/C++ 等語言寫 Makefile),可以參考 NPK 內附範例專案的 package.json。 最終目標『編譯』成二進位格式(Binary) 在與一些企業以及同業分享 Node.js 技術和其未來發展時,時不時會有人提出一個問題:『我們能不能編譯自己寫的 Node.js 程式?』這個問題,往往會開始引發一長串的討論,有一些人為終止這個問題,甚至會開始引用 JavaScript 語言的設計宗旨:『明碼保存,不需要預先編譯』,來強調我們不應該把 JavaScript 的優勢給閹掉。當然,這樣一廂情願的說法,是不可能消除許多人的疑慮,尤其是和 Open Source 路線不熟的企業,或是被『壞客戶欺負』的工程師。 有些眼睛比較亮的人,或許已經發現到,這其實是個複合性的命題,會提出這個問題的人,多半想要知道或得到的是: 能否透過預先編譯 JavaScript 程式,讓執行效能提升。 想要打包自己寫的程式,讓他合併成一個,以方便...