nodejs做爲一個優秀的異步IO框架,其自己就是用來做爲http web服務器使用的,nodejs中的http模塊,提供了不少很是有用的http相關的功能。css
雖然nodejs已經帶有http的處理模塊,可是對於現代web應用程序來講,這或許還不太夠,因而咱們有了express框架,來對nodejs的內容進行擴展。html
今天咱們將會介紹一下使用nodejs和express來開發web應用程序的區別。node
nodejs提供了http模塊,咱們能夠很方便的使用http模塊來建立一個web服務:ios
const http = require('http') const hostname = '127.0.0.1' const port = 3000 const server = http.createServer((req, res) => { res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('welcome to www.flydean.com\n') }) server.listen(port, hostname, () => { console.log(`please visit http://${hostname}:${port}/`) })
上面建立的http服務監聽在3000端口。咱們經過使用createServer方法來建立這個http服務。web
該方法接受一個callback函數,函數的兩個參數分別是 req (http.IncomingMessage 對象)和一個res(http.ServerResponse 對像)。express
在上面的例子中,咱們在response中設置了header和body值,而且以一個end方法來結束response。json
咱們建立好http web服務以後,通常狀況下是從web瀏覽器端進行訪問和調用。可是咱們有時候也須要從nodejs後端服務中調用第三方應用的http接口,下面的例子將會展現如何使用nodejs來調用http服務。axios
先看一個最簡單的get請求:後端
const http = require('http') const options = { hostname: 'www.flydean.com', port: 80, path: '/', method: 'GET' } const req = http.request(options, res => { console.log(`status code: ${res.statusCode}`) res.on('data', d => { console.log(d); }) }) req.on('error', error => { console.error(error) }) req.end()
上面代碼咱們使用了http.request來建立一個request,而且傳入了咱們自帶的options參數。數組
咱們經過res的回調事件來進行相應的處理。
再看一個簡單的post請求:
const http = require('http') const data = JSON.stringify({ name: 'flydean' }) const options = { hostname: 'www.flydean.com', port: 80, path: '/', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': data.length } } const req = http.request(options, res => { console.log(`status code: ${res.statusCode}`) res.on('data', d => { console.log(d); }) }) req.on('error', error => { console.error(error) }) req.write(data) req.end()
post和get類似,不一樣的是options中的method不同,同時put能夠有多種請求類型,因此咱們須要在headers中指定。
一樣的,PUT 和 DELETE 也可使用一樣的方式來調用。
直接使用nodejs底層的http.request有點複雜,咱們須要本身構建options,若是使用第三方庫,好比axios可讓post請求變得更加簡單:
const axios = require('axios') axios .post('http://www.flydean.com', { name: 'flydean' }) .then(res => { console.log(`status code: ${res.statusCode}`) console.log(res) }) .catch(error => { console.error(error) })
上面的例子中,咱們直接使用axios的post請求,並將請求結果封存成了promise,而後經過then和catch來進行相應數據的處理。很是的方便。
在上面的例子中,咱們經過監聽req的data事件來輸出http請求的正文:
res.on('data', d => { console.log(d); }) })
這樣作實際上是有問題的,並不必定可以得到完整的http請求的正文。
由於res的on data事件是在服務器得到http請求頭的時候觸發的,這個時候請求的正文可能尚未傳輸完成,換句話說,請求回調中的request是一個流對象。
咱們須要這樣處理:
const server = http.createServer((req, res) => { let data = [] req.on('data', chunk => { data.push(chunk) }) req.on('end', () => { console.log(JSON.parse(data)); }) })
當每次觸發data事件的時候,咱們將接受到的值push到一個數組裏面,等全部的值都接收完畢,觸發end事件的時候,再統一進行輸出。
這樣處理顯然有點麻煩。
咱們介紹一個在express框架中的簡單方法,使用 body-parser 模塊:
const bodyParser = require('body-parser') app.use( bodyParser.urlencoded({ extended: true }) ) app.use(bodyParser.json()) app.post('/', (req, res) => { console.log(req.body) })
上面的例子中,body-parser對req進行了封裝,咱們只用關注與最後的結果便可。
express是什麼呢?
express是基於 Node.js 平臺,快速、開放、極簡的 web 開發框架。它提供一系列強大的特性,幫助你建立各類 Web 和移動設備應用。
豐富的 HTTP 快捷方法和任意排列組合的 Connect 中間件,讓你建立健壯、友好的 API 變得既快速又簡單。
Express 不對 Node.js 已有的特性進行二次抽象,咱們只是在它之上擴展了 Web 應用所需的基本功能。
咱們看一下怎麼使用Express來搭建一個helloworld:
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!'); }); var server = app.listen(3000, function () { var host = server.address().address; var port = server.address().port; console.log('Example app listening at http://%s:%s', host, port); });
簡單的使用app.listen便可搭建好一個http web服務。
有了web服務,咱們須要對不一樣的請求路徑和請求方式進行不一樣的處理,這時候就須要使用到了express路由功能:
// 對網站首頁的訪問返回 "Hello World!" 字樣 app.get('/', function (req, res) { res.send('Hello World!');}); // 網站首頁接受 POST 請求 app.post('/', function (req, res) { res.send('Got a POST request');}); // /user 節點接受 PUT 請求 app.put('/user', function (req, res) { res.send('Got a PUT request at /user');}); // /user 節點接受 DELETE 請求 app.delete('/user', function (req, res) { res.send('Got a DELETE request at /user');});
更高級一點的,咱們還能夠在請求路徑中作路由匹配:
// 匹配 acd 和 abcd app.get('/ab?cd', function(req, res) { res.send('ab?cd');}); // 匹配 abcd、abbcd、abbbcd等 app.get('/ab+cd', function(req, res) { res.send('ab+cd'); }); // 匹配 abcd、abxcd、abRABDOMcd、ab123cd等 app.get('/ab*cd', function(req, res) { res.send('ab*cd'); }); // 匹配 /abe 和 /abcde app.get('/ab(cd)?e', function(req, res) { res.send('ab(cd)?e');}); // 匹配任何路徑中含有 a 的路徑: app.get(/a/, function(req, res) { res.send('/a/'); }); // 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等 app.get(/.*fly$/, function(req, res) { res.send('/.*fly$/'); });
有時候,一個請求可能有多個處理器,express提供了路由句柄(中間件)的功能,咱們可自由組合處理程序。
注意,在路由句柄中,咱們須要調用next方法,來觸發下一個路由方法。
var cb0 = function (req, res, next) { console.log('CB0'); next();} var cb1 = function (req, res, next) { console.log('CB1'); next();} app.get('/example/d', [cb0, cb1], function (req, res, next) { console.log('response will be sent by the next function ...'); next(); }, function (req, res) { res.send('Hello from D!'); });
上面的請求會通過cb0,cb1和自定義的兩個function,最終結束。
express提供了不少響應方法API,能夠方便咱們的代碼編寫:
方法 | 描述 |
---|---|
res.download() | 提示下載文件。 |
res.end() | 終結響應處理流程。 |
res.json() | 發送一個 JSON 格式的響應。 |
res.jsonp() | 發送一個支持 JSONP 的 JSON 格式的響應。 |
res.redirect() | 重定向請求。 |
res.render() | 渲染視圖模板。 |
res.send() | 發送各類類型的響應。 |
res.sendFile | 以八位字節流的形式發送文件。 |
res.sendStatus() | 設置響應狀態代碼,並將其以字符串形式做爲響應體的一部分發送。 |
一般來講,靜態資源是不須要服務端進行處理的,在express中,可使用express.static來指定靜態資源的路徑:
app.use(express.static('public')); 如今,public 目錄下面的文件就能夠訪問了。 http://localhost:3000/images/kitten.jpg http://localhost:3000/css/style.css http://localhost:3000/js/app.js http://localhost:3000/images/bg.png http://localhost:3000/hello.html //多個靜態資源目錄 app.use(express.static('public')); app.use(express.static('files')); //靜態前綴 app.use('/static', express.static('public')); http://localhost:3000/static/images/kitten.jpg http://localhost:3000/static/css/style.css
web應用固然須要html文件,express中可使用多種模板語言,讓編寫html頁面更加容易。若是想要使用模板引擎。咱們可使用下面的步驟:
views, 放模板文件的目錄,好比: app.set('views', './views')
view engine, 模板引擎,好比: app.set('view engine', 'jade')
在 views 目錄下生成名爲 index.jade 的 Jade 模板文件,內容以下:
html head title!= title body h1!= message
//配置route 規則 app.get('/', function (req, res) { res.render('index', { title: 'Hey', message: 'Hello there!'}); });
nodejs和express是很是方便的http web服務框架,但願你們可以喜歡。
本文做者:flydean程序那些事
本文連接:http://www.flydean.com/nodejs-http-express/
本文來源:flydean的博客
歡迎關注個人公衆號:「程序那些事」最通俗的解讀,最深入的乾貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!