iT邦幫忙

DAY 3
0

Node.js 學習筆記系列 第 3

Node.js學習筆記二:Node.js路由(Routing)處理基礎

  • 分享至 

  • xImage
  •  

(本文同步發表於NodeJust.com

Hello World的例子裡,學習了Node.js的回應(Response)的基礎,今天來看一下請求(Request)的部分。以下是今天的學習重點:

1. Node.js的url模組;URL的結構:pathname與query。

2. 請求(Request)的初體驗:req.url。

3. 建立自己的模組,匯出模組中的函數:exports.外部引用名稱 = 內部函數名稱。

4. 理解路由的邏輯。

一、瞭解URL的結構並取得pathname。

請求(Request)基本上就是處理URL以及GET/POST,我們先來看URL的部分。URL的處理就是路由(Routing)。首先我們要明白URL的結構,請看以下例子:

http://localhost:3000/blog?user=zack

我們只要看"/"之後,問號之前,也就是"blog"的部分,我們叫它:pathname。問號之後,也就是"user=zack"的部分,我們叫它:query。

這個命名是來自我們今天要用到的一個Node.js模組:url模組。以下是今天第一個例子(index.js):

var http = require("http");
var url = require("url");

function onRequest(req, res) {
  var pathname = url.parse(req.url).pathname;
  console.log("Request for " + pathname + " received.");
  res.writeHead(200, {"Content-Type": "text/plain"});
  res.end("Hello World");
}

http.createServer(onRequest).listen(3000);
console.log("Server has started to listen at port: 3000.");

我們引進url模組,並將之賦值給變數"url"var url = require("url"); 。

req.url裡包含整個URL,我們用url.parse(req.url).pathname 提取pathname的部分,並將之賦值給"pathname"變數。然後我們就可以根據pathname來決定該顯示什麼內容,例如,當pathname的值為"blog"的時候,我們就顯示部落格;當pathname為"about"的時候就顯示"關於我們"頁面。這個例子裡則是什麼都沒做,只是在console顯示所訪問的位置。因此,當你在瀏覽器輸入:localhost:3000/blog,畫面並不會變化,只有console會顯示:"Request for /blog received."

二、理清路由處理的基本邏輯

至於要怎麼處理路由呢?最簡單的方法就是用IF來進行判斷。這顯然不是一個好方法,特別是當網站變得越來越大,需要處理的路由越來越多的時候。雖然網站會變多大,我們想像不到;但至少我們可以把路由的處理獨立出來,作為一個函數,就算將來要改動路由,對主程式的影響也能降到最低。整個程式也會更清晰。

現在來想想route()函數的內容該怎樣。暫且設定三種情況要處理:

  1. pathname為"/":顯示主頁;

  2. pathname為"blog":顯示部落格;

  3. pathname為其他:顯示404 Not Found。

我們可以建立一個handle[pathname]的變數,根據pathname的不同而執行不同的功能:

  1. pathname為"/",即handle["/"]:顯示主頁;

  2. pathname為"blog",即handle["blog"]:顯示部落格;

  3. pathname為其他,即handle[pathname]不存在:顯示404 Not Found。​

因此要先給handle["/"]跟handle["blog"]分別建立顯示用的函數,將這兩個函數放在同一個文件,以一個模組的形式來提供這個兩功能以供稍後的route()函數使用。方法是:新增一個文件,命名為showPage.js,內容如下:

function home() {
  console.log("This is the home page.");
}

function blog() {
  console.log("This is the blog page.");
}

exports.home = home;
exports.blog = blog;

最後兩句就是將本文件中的功能匯出,格式是:exports.外部引用名稱 = 內部函數名稱。這個文件其實就是一個獨立的模組。在下面的route()函數裡,我們會看到具體如何使用。

接著將這兩個函數賦值給handle[],為什麼是shwoPage.home?下面再解釋:

var handle = {}
handle["/"] = showPage.home;
handle["/blog"] = showPage.blog;

判斷handle[pathname]是否為有效的函數,是則執行;否則顯示404:

if (typeof handle[pathname] === 'function') {
  handle[pathname]();
} else {
  console.log("404 Not Found: " + pathname);
}

之前,我們將函數賦值給了handle[pathname],這裡只是加一對小括號就能調用該函數handlepathname; 。是不是非常方便?

三、路由的實踐

整個邏輯清晰了,正式來建立route()函數。我們把route()放在一個獨立的文件裡,並在結尾將函數匯出,讓主程式(index.js)調用。新增一個route.js的文件,其內容如下:

var showPage = require("./showPage");

function route(pathname) {

  var handle = {}
  handle["/"] = showPage.home;
  handle["/blog"] = showPage.blog;

  if (typeof handle[pathname] === 'function') {
    handle[pathname]();
  } else {
    console.log("404 Not Found " + pathname);
  }
}

exports.route = route;

首先,我們用var showPage = require("./showPage"); ,將showPage.js文件(模組)引入並賦值給showPage變數,這樣我們就能用showPage.home 以及showPage.blog (不用加小括號)來調用裡面的兩個函數。下面我們就把這兩個函數分別賦值給handle[]變數。然後進行路由判斷。最後我們也將route()函數匯出exports.route = route; ,以便主程式index.js使用。

所以route.js也是一個獨立的模組。這樣,我們一共建立了兩個自訂模組:showPage.js與route.js。

現在的index.js變成這樣:

var http = require("http");
var url = require("url");
var router = require("./route");

function onRequest(req, res) {
  var pathname = url.parse(req.url).pathname;

  router.route(pathname);

  res.writeHead(200, {"Content-Type": "text/plain"});
  res.end("Hello World");
}

http.createServer(onRequest).listen(3000);
console.log("Server has started to listen at port: 3000.");

先是匯入了route.js模組,並賦值給router變數。然後增加了router.route(pathname); 這一行,讓router來幫我們處理所有的路由。

現在你用瀏覽器打開:localhost:3000,你會看到console裡輸出:"This is the home page."。

當打開:localhost:3000/blog,會看到console裡輸出:"This is the blog page."。

當打開:localhost:3000/xxx,會看到console裡輸出:"404 Not Found /xxx"。

另外你也會看到:"404 Not Found /favicon.ico",這是之前提過的對favicon的請求,暫時先不用理它。

四、還沒完成的部份:輸出到網頁?

到這裡為止,我們的路由只輸出到console,沒有真正輸出到網頁的部份。這是因為會涉及到Node.js非同步特性帶來的問題,所以下一篇再來詳細討論這個部份。

五、總結

同樣來回顧今天的學習目標。

1. Node.js的url模組;URL的結構:pathname與query。
--匯入模組var url = require("url");
--取得某URL的pathname:url.parse(URL).pathname;

2. 請求(Request)的初體驗:
--req.url 包含完整URL,要使用上面的url模組來分解。

3. 建立自己的模組,匯出模組中的函數。
--以一個獨立文件的形式,結尾將內部功能匯出:exports.外部引用名稱 = 內部函數名稱
--要使用一個模組:var router = require("./route"); 不用加副檔名.js。

4. 理解路由的邏輯。
--理解handle[pathname] 跟handlepathname 的神奇之處。

參考資料:

  1. The Node Beginner Book

[image credit: kamillehmann]


上一篇
Node.js學習筆記一:Node.js的Hello World
下一篇
Node.js學習筆記三:Blocking與Non-blocking的思考
系列文
Node.js 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言