Node入門

服務端JavaScript

JavaScript最先是運行在瀏覽器上的,瀏覽器只是提供了一個上下文,它定義了JavaScript能夠作什麼,並無指明JavaScript語言自己能夠作什麼,實際上,JavaScript是一門完整的語言,能夠使用在不一樣的上下文中,要實如今後臺運行JavaScript代碼,代碼須要先被解釋而後執行,Node.js的原理就是如此,他使用Google的V8虛擬機來解釋和執行JavaScript代碼,所以,NodeJs事實上既是一個運行時環境,同時又是一個庫。javascript

Node.js的Web應用

一個基礎的HTTP服務器

新建一個server.js文件並寫入以下代碼:java

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);

使用Node.js執行腳本node

node server.js

在瀏覽器訪問http://localhost:8888/,能夠看到網頁。web

用這樣的代碼也能夠實現:瀏覽器

var http = require("http");

function onRequest(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);

基於事件驅動的回調

var http = require("http");

function onRequest(request, response) {
  console.log("Request received.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);

console.log("Server has started.");

運行後,會立刻在命令行輸出「Server has started」,在瀏覽器輸入地址訪問後(發出請求),「Request has received.」就會在命令行中出現。服務器

模塊化

var http = require("http");

function start() {
  function onRequest(request, response) {
    console.log("Request received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

咱們如今就能夠建立咱們的主文件 index.js 並在其中啓動咱們的HTTP了,雖然服務器的代碼還在 server.js 中。模塊化

建立 index.js 文件並寫入如下內容:函數

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

server.start();

請求的路由

請求的數據都回包含在request對象,該對象做爲onRequest()回調函數的第一個參數傳遞,爲了解析這些數據,咱們須要url模塊和queryString模塊。ui

url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&hello=world
                                ---       -----
                                 |          |
                                 |          |
              querystring(string)["foo"]    |
                                            |
                         querystring(string)["hello"]

改server.js爲以下:url

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

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

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

如今咱們編寫路由,建一個route.js文件以下:

function route(pathname) {
  console.log("About to route a request for " + pathname);
}

exports.route = route;

擴展server.js以整合路由:

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

function start(route) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(pathname);

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

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

同時,咱們會相應擴展index.js,使得路由函數能夠被注入到服務器中:

var server = require("./server");
var router = require("./router");

server.start(router.route);

路由給真正的請求處理程序

建立一個requestHandlers模塊,並對於每個請求處理程序,添加一個佔位用函數,並導出

function start() {
  console.log("Request handler 'start' was called.");
}

function upload() {
  console.log("Request handler 'upload' was called.");
}

exports.start = start;
exports.upload = upload;

擴展index.js

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;

server.start(router.route, handle);

修改server.js

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

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(handle, pathname);

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

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

修改route.js

function route(handle, pathname) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    handle[pathname]();
  } else {
    console.log("No request handler found for " + pathname);
  }
}

exports.route = route;

很差的實現方式

讓請求處理程序經過onRequest函數直接返回(return())他們要展現給用戶的信息。

咱們先就這樣去實現,而後再來看爲何這不是一種很好的實現方式。

requestHandler.js修改成以下形式:

function start() {
  console.log("Request handler 'start' was called.");
  return "Hello Start";
}

function upload() {
  console.log("Request handler 'upload' was called.");
  return "Hello Upload";
}

exports.start = start;
exports.upload = upload;

一樣的,請求路由須要將請求處理程序返回給它的信息返回給服務器。所以,咱們須要將router.js修改成以下形式:

function route(handle, pathname) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    return handle[pathname]();
  } else {
    console.log("No request handler found for " + pathname);
    return "404 Not found";
  }
}

exports.route = route;

最後,咱們須要對咱們的server.js進行重構以使得它可以將請求處理程序經過請求路由返回的內容響應給瀏覽器,以下所示:

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

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    response.writeHead(200, {"Content-Type": "text/plain"});
    var content = route(handle, pathname)
    response.write(content);
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

若是咱們運行重構後的應用,一切都會工做的很好:請求http://localhost:8888/start,瀏覽器會輸出「Hello Start」,請求http://localhost:8888/upload會輸出「Hello Upload」,而請求http://localhost:8888/foo 會輸出「404 Not found」。

相關文章
相關標籤/搜索