Express/Node introduction

2018-05-15 17:26 更新
先決條件: 基本的計(jì)算機(jī)素養(yǎng)。 對(duì)服務(wù)器端網(wǎng)站編程的一般了解,特別是對(duì) 網(wǎng)站中的客戶端 - 服務(wù)器互動(dòng)。
目的: 熟悉Express是什么,它如何適應(yīng)Node,它提供了什么功能,以及Express應(yīng)用程序的主要構(gòu)建塊。

什么是Express和Node?

節(jié)點(diǎn)(或更正式的 Node.js )是一個(gè)開源的跨平臺(tái), 運(yùn)行時(shí)環(huán)境,允許開發(fā)人員在 JavaScript 中創(chuàng)建各種服務(wù)器端工具和應(yīng)用程序。 運(yùn)行時(shí)期望在瀏覽器上下文之外使用(即直接在計(jì)算機(jī)或服務(wù)器OS上運(yùn)行)。 因此,環(huán)境省略了瀏覽器特定的JavaScript API,并支持更傳統(tǒng)的操作系統(tǒng)API,包括HTTP和文件系統(tǒng)庫。

從Web服務(wù)器開發(fā)的角度來看,Node有很多好處:

  • Great performance! Node has been designed to optimize throughput and scalability in web applications and is a very good match for many common web-development problems (e.g. real-time web applications).
  • Code is written in "plain old JavaScript", which means that less time is spent dealing with "context shift" between languages when you're writing both browser and web server code.
  • JavaScript is a relatively new programming language and benefits from improvements in language design when compared to other traditional web-server languages (e.g. Python, PHP, etc.) Many other new and popular languages compile/convert into JavaScript so you can also use CoffeeScript, ClosureScript, Scala, LiveScript, etc.
  • The node package manager (NPM) provides access to hundreds of thousands of reusable packages. It also has best-in-class dependency resolution and can also be used to automate most of the build toolchain.
  • It is portable, with versions running on Microsoft Windows, OS X, Linux, Solaris, FreeBSD, OpenBSD, WebOS, and NonStop OS. Furthermore, it is well-supported by many web hosting providers, that often provide specific infrastructure and documentation for hosting Node sites.
  • It has a very active third party ecosystem and developer community, with lots of people who are willing to help.

您可以簡(jiǎn)單地創(chuàng)建一個(gè)簡(jiǎn)單的Web服務(wù)器,以便只使用Node HTTP包來響應(yīng)任何請(qǐng)求,如下所示。 這將創(chuàng)建一個(gè)服務(wù)器并監(jiān)聽URL http://127.0.0.1:8000/ 上的任何類型的HTTP請(qǐng)求; 當(dāng)接收到它時(shí),它將發(fā)送純文本響應(yīng)"Hello World"。

//Load HTTP module
var http = require("http");

//Create HTTP server and listen on port 8000 for requests
http.createServer(function (request, response) {

   // Set the response HTTP header with HTTP status and Content type
   response.writeHead(200, {'Content-Type': 'text/plain'});
   
   // Send the response body "Hello World"
   response.end('Hello World\n');
}).listen(8000);

// Print URL for accessing server
console.log('Server running at http://127.0.0.1:8000/')

Node本身不直接支持其他常見的Web開發(fā)任務(wù)。 如果要為不同的HTTP動(dòng)詞添加特定的處理(例如 GET POST , DELETE 等) 路徑("路由"),服務(wù)靜態(tài)文件或使用模板動(dòng)態(tài)創(chuàng)建響應(yīng),那么您將需要自己編寫代碼,或者您可以避免重復(fù)發(fā)明輪和使用Web框架!

Express 是最受歡迎的 Node Web框架,是許多其他基礎(chǔ)庫 受歡迎的節(jié)點(diǎn)網(wǎng)絡(luò)框架。 它提供了以下機(jī)制:

  • Write handlers for requests with different HTTP verbs at different URL paths (routes).
  • Integrate with "view" rendering engines in order to generate responses by inserting data into templates.
  • Set common web application settings like the port to use for connecting, and the location of templates that are used for rendering the response.
  • Add additional request processing "middleware" at any point within the request handling pipeline.

雖然 Express 本身是相當(dāng)簡(jiǎn)約的,但開發(fā)人員已經(jīng)創(chuàng)建了兼容的中間件包來解決幾乎任何Web開發(fā)問題。 有些庫可以使用Cookie,會(huì)話,用戶登錄,URL參數(shù), POST 數(shù)據(jù),安全標(biāo)題和更多 您可以在 Express中間件(以及)中找到由Express小組維護(hù)的中間件包列表 一些流行的第三方包的列表)。

注意:這種靈活性是一把雙刃劍。 有中間件包來解決幾乎任何問題或需求,但是制定正確的包使用有時(shí)可能是一個(gè)挑戰(zhàn)。 還沒有"正確的方法"來構(gòu)建應(yīng)用程序,并且您可能在Internet上發(fā)現(xiàn)的許多示例不是最佳的,或者只顯示了開發(fā)Web應(yīng)用程序所需要做的一小部分。

它從哪里來的?

節(jié)點(diǎn)最初是在2009年發(fā)布的,僅適用于Linux。NPM軟件包管理器于2010年發(fā)布,本地Windows支持在2012年添加。當(dāng)前版本是節(jié)點(diǎn)4。 如果您想了解更多信息,請(qǐng)深入了解維基百科)。

Express最初于2010年11月發(fā)布,目前使用的是API的第4版。 您可以查看更改日志,了解有關(guān)當(dāng)前版本更改的信息, "external"> GitHub 以獲取更詳細(xì)的歷史發(fā)行說明。

Web框架的普及是很重要的,因?yàn)樗且粋€(gè)指示符,它是否將繼續(xù)被維護(hù),以及在文檔,附加庫和技術(shù)支持方面可能有哪些資源可用。

對(duì)于服務(wù)器端框架的流行度,目前還沒有任何現(xiàn)成和確定的衡量標(biāo)準(zhǔn)(雖然 Hot Frameworks 等網(wǎng)站 使用諸如計(jì)算GitHub項(xiàng)目數(shù)量和每個(gè)平臺(tái)的StackOverflow問題的機(jī)制來評(píng)估流行度)。 一個(gè)更好的問題是Node和Express是否"足夠流行",以避免不受歡迎的平臺(tái)的問題。 它們是否繼續(xù)演變? 如果你需要它,你能得到幫助嗎? 如果你學(xué)習(xí)Express,你有機(jī)會(huì)獲得有報(bào)酬的工作嗎?

根據(jù)使用Express的知名公司的數(shù)量, 人們對(duì)代碼庫的貢獻(xiàn),以及提供免費(fèi)和付費(fèi)支持的人數(shù),那么是的,Express 是一個(gè)流行的框架!

是Express意見?

Web框架通常將自己稱為"意見"或"不庸俗"。

意見框架是那些對(duì)"正確的方式"處理任何特定任務(wù)有意見的框架。 他們經(jīng)常支持特定領(lǐng)域的快速發(fā)展(解決特定類型的問題),因?yàn)檎_的做任何事情的方式通常是很好理解的和有據(jù)可查的。 然而,他們?cè)诮鉀Q其主域以外的問題時(shí)可能不那么靈活,并且傾向于為他們可以使用的組件和方法提供較少的選擇。

相比之下,未分離的框架對(duì)于將組件粘合在一起以實(shí)現(xiàn)目標(biāo)的最佳方式,或者甚至應(yīng)該使用什么組件的限制要少得多。 它們使開發(fā)人員更容易使用最合適的工具來完成特定的任務(wù),盡管需要自己找到這些組件的成本。

Express是未經(jīng)宣傳的。 你幾乎可以將任何兼容的中間件插入請(qǐng)求處理鏈,幾乎任何你喜歡的順序。 您可以在一個(gè)文件或多個(gè)文件中構(gòu)建應(yīng)用程序,并使用任何目錄結(jié)構(gòu)。 你有時(shí)可能會(huì)覺得你有太多的選擇!

Express代碼是什么樣子?

在傳統(tǒng)的數(shù)據(jù)驅(qū)動(dòng)網(wǎng)站中,web應(yīng)用程序等待來自web瀏覽器(或其他客戶端)的HTTP請(qǐng)求。 當(dāng)接收到請(qǐng)求時(shí),應(yīng)用程序基于包含在 POST 數(shù)據(jù)或 GET 數(shù)據(jù)中的URL模式和可能的相關(guān)信息來確定需要什么動(dòng)作。 根據(jù)需要,它然后可以從數(shù)據(jù)庫讀取或?qū)懭胄畔⒒驁?zhí)行滿足請(qǐng)求所需的其他任務(wù)。 應(yīng)用程序然后將向web瀏覽器返回響應(yīng),通常動(dòng)態(tài)地創(chuàng)建HTML頁面以供瀏覽器通過將檢索到的數(shù)據(jù)插入到HTML模板中的占位符來顯示。

Express提供了指定為特定HTTP動(dòng)詞( GET , POST , SET 等)和URL模式 路由"),以及指定使用哪個(gè)模板("視圖")引擎,模板文件所在的位置以及用于呈現(xiàn)響應(yīng)的模板的方法。 您可以使用Express中間件添加對(duì)Cookie,會(huì)話和用戶的支持,獲取 POST / GET 參數(shù)等。您可以使用Node支持的任何數(shù)據(jù)庫機(jī)制 不定義任何數(shù)據(jù)庫相關(guān)行為)。

以下部分解釋了使用Express 和節(jié)點(diǎn)代碼時(shí)會(huì)遇到的一些常見問題。

Helloworld快遞

首先,讓我們考慮標(biāo)準(zhǔn)Express Hello World 示例(我們將在下面討論此部分的每個(gè)部分 ,并在以下部分)。

提示:如果您已安裝了Node和Express(或如果您按照下一篇文章中所示安裝它們),則可以 將此代碼保存在名為 app.js 的文件中,并通過調(diào)用 node app.js 在命令提示符處運(yùn)行它。

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

前兩行 require()(import)express模塊并創(chuàng)建一個(gè) ">快速應(yīng)用。 這個(gè)傳統(tǒng)上被命名為 app 的對(duì)象具有路由HTTP請(qǐng)求,配置中間件,渲染HTML視圖,注冊(cè)模板引擎和修改 /expressjs.com/en/4x/api.html#app.settings.table\">應(yīng)用程序設(shè)置,用于控制應(yīng)用程序的行為(例如,環(huán)境模式,路由定義是否區(qū)分大小寫等)

代碼的中間部分(以 app.get 開頭的三行)顯示了路由定義。 app.get()方法指定一個(gè)回調(diào)函數(shù),只要有一個(gè)路徑(\'/\' )相對(duì)于站點(diǎn)根。 回調(diào)函數(shù)將請(qǐng)求和響應(yīng)對(duì)象作為參數(shù),只需調(diào)用 send() ,返回字符串"Hello World!"。

最后一個(gè)塊啟動(dòng)端口\'3000\'上的服務(wù)器,并向控制臺(tái)打印一個(gè)日志注釋。 在服務(wù)器運(yùn)行時(shí),您可以在瀏覽器中轉(zhuǎn)到 localhost:3000 ,查看返回的示例響應(yīng)。

導(dǎo)入和創(chuàng)建模塊

模塊是一個(gè)JavaScript庫/文件,您可以使用Node的 require()函數(shù)將其導(dǎo)入其他代碼。 本身是一個(gè)模塊,我們?cè)?em> Express 應(yīng)用程序中使用的中間件和數(shù)據(jù)庫庫也是一樣。

下面的代碼顯示了如何使用 Express 框架作為示例,按名稱導(dǎo)入模塊。 首先我們調(diào)用 require()函數(shù),將模塊的名稱指定為字符串(\'express\' 代碼>),并調(diào)用返回的對(duì)象以創(chuàng)建 Express應(yīng)用程序。 然后我們可以訪問應(yīng)用程序?qū)ο蟮膶傩院秃瘮?shù)。

var express = require('express');
var app = express();

您還可以創(chuàng)建自己的模塊,可以以相同的方式導(dǎo)入。

提示:您將希望創(chuàng)建自己的模塊,因?yàn)檫@允許您將代碼整理成可管理的部分 - 單一的單文件應(yīng)用程序很難理解和維護(hù)。 使用模塊還可以幫助您管理命名空間,因?yàn)橹挥性谀褂媚K時(shí)才導(dǎo)入顯式導(dǎo)出的變量。

要使對(duì)象在模塊外部可用,您只需要將它們分配給 exports 對(duì)象。 例如,下面的 square.js 模塊是導(dǎo)出 area() perimeter()方法的文件:

exports.area = function (width) { return width * width; };
exports.perimeter = function (width) { return 4 * width; };

我們可以使用 require()導(dǎo)入此模塊,然后調(diào)用導(dǎo)出的方法如下所示:

var square = require('./square'); // Here we require() the name of the file without the (optional) .js file extension
console.log('The area of a square with a width of 4 is ' + square.area(4));

注意:您還可以指定模塊的絕對(duì)路徑(或名稱,如我們最初所做的那樣)。

如果要在一個(gè)分配中導(dǎo)出完整的對(duì)象,而不是一次創(chuàng)建一個(gè)屬性,請(qǐng)將其分配給 module.exports ,如下所示(您也可以執(zhí)行此操作以創(chuàng)建導(dǎo)出的根 對(duì)象的構(gòu)造函數(shù)或其他函數(shù)):

module.exports = {
  area: function(width) {
    return width * width;
  },
       
  perimeter: function(width) {
    return 4 * width;
  }
};

有關(guān)模塊的更多信息,請(qǐng)參閱模塊(節(jié)點(diǎn)API文檔)。

使用異步API

JavaScript代碼經(jīng)常使用異步而不是同步API進(jìn)行可能需要一些時(shí)間才能完成的操作。 同步API是每個(gè)操作必須在下一個(gè)操作開始之前完成的API。 例如,以下日志函數(shù)是同步的,并將按順序(第一,第二)將文本打印到控制臺(tái)。

console.log('First');
console.log('Second');

相比之下,異步API是其中API將開始操作并立即返回(在操作完成之前)的API。 一旦操作完成,API將使用一些機(jī)制來執(zhí)行額外的操作。 例如,下面的代碼將打印出"Second,F(xiàn)irst",因?yàn)榧词?code> setTimeout()方法被首先調(diào)用,并立即返回,操作不會(huì)完成幾秒鐘。

setTimeout(function() {
   console.log('First');
   }, 3000);
console.log('Second');

使用非阻塞異步API在Node上比在瀏覽器中更重要,因?yàn)?em> Node 是一個(gè)單線程事件驅(qū)動(dòng)的執(zhí)行環(huán)境。 "單線程"意味著對(duì)服務(wù)器的所有請(qǐng)求都在同一線程上運(yùn)行(而不是生成到單獨(dú)的進(jìn)程)。 這種模式在速度和服務(wù)器資源方面非常高效,但它的意思是,如果你的任何函數(shù)調(diào)用同步方法需要很長(zhǎng)時(shí)間來完成,它們將阻塞不僅當(dāng)前請(qǐng)求,而每隔一個(gè)請(qǐng)求被處理 您的Web應(yīng)用程序。

異步API有多種方式可以通知應(yīng)用程序已完成。 最常見的方法是在調(diào)用異步API時(shí)注冊(cè)回調(diào)函數(shù),該操作將在操作完成時(shí)調(diào)用。 這是上面使用的方法。

提示:如果您有一系列必須按順序執(zhí)行的依賴異步操作,則使用回調(diào)可能相當(dāng)"混亂",因?yàn)檫@會(huì)導(dǎo)致多級(jí)嵌套回調(diào)。 這個(gè)問題通常被稱為"回調(diào)地獄"。 通過良好的編碼實(shí)踐(請(qǐng)參閱 http://callbackhell.com/ )可以減少此問題,使用類似 a class ="external"> async ,甚至移至ES5的功能,例如 org / zh-CN / docs / Web / JavaScript / Reference / Global_Objects / Promise"> Promises 。

注意: Node和Express的常見約定是使用錯(cuò)誤優(yōu)先回調(diào)。 在這個(gè)約定中,回調(diào)函數(shù)中的第一個(gè)值是錯(cuò)誤值,而后續(xù)參數(shù)包含成功數(shù)據(jù)。 有一個(gè)很好的解釋為什么這種方法是有用的在這個(gè)博客: -js /%C2%A0"> Node.js方式 - 了解錯(cuò)誤 - 第一回調(diào)(fredkschott.com)。

創(chuàng)建路由處理程序

在我們的 Hello World Express示例中,我們定義了一個(gè)(callback)路由處理函數(shù),用于向網(wǎng)站根(\'/\' )。

app.get('/', function (req, res) {
  res.send('Hello World!');
});

回調(diào)函數(shù)接受請(qǐng)求和響應(yīng)對(duì)象作為參數(shù)。 在這種情況下,該方法只需調(diào)用 send() 代碼>上的響應(yīng)返回字符串"Hello World!" 有用于結(jié)束請(qǐng)求/響應(yīng)周期的其他響應(yīng)方法數(shù) ,例如您可以調(diào)用 res.json() / code>發(fā)送JSON響應(yīng)或 res.sendFile() a> 發(fā)送文件。

JavaScript提示:您可以在回調(diào)函數(shù)中使用任何您喜歡的參數(shù)名稱; 當(dāng)回調(diào)被調(diào)用時(shí),第一個(gè)參數(shù)總是請(qǐng)求,第二個(gè)參數(shù)總是響應(yīng)。 命名它們是有意義的,以便可以在回調(diào)的主體中標(biāo)識(shí)您正在使用的對(duì)象。

對(duì)象也提供了為所有其他HTTP動(dòng)詞定義路線處理程序的方法,大多數(shù)使用方式完全相同: post(), put (), delete() options() , lock(), mkcol(), move(), purge ), proppatch(), unlock(), report(), mkactivity ), checkout(), checkout() > notify(), subscribe() unsubscribe() 代碼>和 connect()。

有一個(gè)特殊的路由方法, app.all(),它將被調(diào)用以響應(yīng)任何HTTP方法。 這用于在所有請(qǐng)求方法的特定路徑加載中間件函數(shù)。 下面的示例(來自Express文檔)顯示了一個(gè)處理程序,它將對(duì) / secret 的請(qǐng)求執(zhí)行,而不考慮所使用的HTTP動(dòng)詞(假設(shè)它受到 "https://nodejs.org/api/http.html#http_http_methods\">http模塊)。

app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...')
  next() // pass control to the next handler
})

路由允許您匹配URL中的特定字符模式,并從URL中提取一些值,并將它們作為參數(shù)傳遞給路由處理程序(作為作為參數(shù)傳遞的請(qǐng)求對(duì)象的屬性)。

通常,將站點(diǎn)的特定部分的路由處理器組合在一起并使用公共路由前綴來訪問它們是有用的(例如,具有Wiki的站點(diǎn)可以在一個(gè)文件中具有所有與wiki相關(guān)的路由,并且使用路由前綴 的 / wiki / )。 使用 快遞 .Router 對(duì)象。 例如,我們可以在名為 wiki.js 的模塊中創(chuàng)建wiki路由,然后導(dǎo)出 Router 對(duì)象,如下所示:

// wiki.js - Wiki route module

var express = require('express')
var router = express.Router()

// Home page route
router.get('/', function (req, res) {
  res.send('Wiki home page')
})

// About page route
router.get('/about', function (req, res) {
  res.send('About this wiki')
})

module.exports = router

注意:向 Router 對(duì)象添加路由就像向 app 對(duì)象添加路由(如前所示)。

要在我們的主要應(yīng)用程序文件中使用路由器,我們將 require()路由模塊( wiki.js ),然后調(diào)用 use Express 應(yīng)用程序上將路由器添加到中間件處理路徑。 然后,可以從 / wiki / 正常"> / wiki / about / 。

var wiki = require('./wiki.js')
// ...
app.use('/wiki', wiki)

我們將向您展示更多關(guān)于使用路由的信息,特別是關(guān)于使用 Router ,稍后在鏈接的部分 -US / docs / Learn / Server-side / Express_Nodejs / routes">路由和控制器

使用中間件

中間件廣泛用于Express應(yīng)用程序,用于從提供靜態(tài)文件到錯(cuò)誤處理,到壓縮HTTP響應(yīng)的任務(wù)。 路由功能通過向HTTP客戶端返回一些響應(yīng)來結(jié)束HTTP請(qǐng)求 - 響應(yīng)循環(huán),而中間件功能通常對(duì)請(qǐng)求或響應(yīng)執(zhí)行一些操作,然后調(diào)用"堆棧"中的下一個(gè)功能, 可能更多的中間件或路由處理程序。 中間件被調(diào)用的順序取決于應(yīng)用程序開發(fā)人員。

注意:中間件可以執(zhí)行任何操作,執(zhí)行任何代碼,更改請(qǐng)求和響應(yīng)對(duì)象,也可以結(jié)束請(qǐng)求 - 響應(yīng)周期。 如果它沒有結(jié)束循環(huán),它必須調(diào)用 next()將控制傳遞給下一個(gè)中間件函數(shù)(或者請(qǐng)求將被掛起)。

大多數(shù)應(yīng)用程序?qū)⑹褂玫谌街虚g件,以簡(jiǎn)化常見的網(wǎng)站開發(fā)任務(wù),如使用Cookie,會(huì)話,用戶身份驗(yàn)證,訪問請(qǐng)求 POST 和JSON數(shù)據(jù),日志記錄等 。您可以找到 Express小組維護(hù)的中間件軟件包列表(其中還包括其他 流行的第三方包)。 其他Express包在NPM包管理器上可用。

要使用第三方中間件,您首先需要使用NPM將其安裝到您的應(yīng)用程序中。 例如,要安裝摩根 HTTP請(qǐng)求記錄器中間件,您需要執(zhí)行此操作 :

$ npm install morgan

然后,您可以在 Express應(yīng)用程序?qū)ο?/em>上調(diào)用 use()將中間件添加到堆棧:

var express = require('express');
var logger = require('morgan');
var app = express();
app.use(logger('dev'));
...

注意:中間件和路由功能按照聲明的順序調(diào)用。 對(duì)于一些中間件,順序很重要(例如,如果會(huì)話中間件依賴于cookie中間件,則必須首先添加cookie處理程序)。 幾乎總是在設(shè)置路由之前調(diào)用中間件,或者路由處理程序?qū)o法訪問中間件添加的功能。

您可以編寫自己的中間件函數(shù),并且可能必須這樣做(如果只創(chuàng)建錯(cuò)誤處理代碼)。 中間件函數(shù)和路由處理程序回調(diào)之間的區(qū)別在于中間件函數(shù)具有第三個(gè)參數(shù) next ,如果中間件函數(shù)不完成請(qǐng)求, 循環(huán)(當(dāng)調(diào)用中間件函數(shù)時(shí),它包含必須調(diào)用的 next 函數(shù))。

您可以使用 app.use() app.add()向處理鏈添加中間件函數(shù),具體取決于您是否要將中間件應(yīng)用于所有響應(yīng) 或具有特定HTTP動(dòng)詞( GET , POST 等)的響應(yīng)。 您可以在兩種情況下指定相同的路由,但在調(diào)用 app.use()時(shí)路由是可選的。

下面的示例顯示了如何使用這兩種方法添加中間件函數(shù),以及使用/不使用路由。

var express = require('express')
var app = express()

// An example middleware function
var a_middleware_function = function(req, res, next) {
? //... perform some operations
? next(); //Call next() so Express will call the next middleware function in the chain.
}

// Function added with use() for all routes and verbs
app.use(a_middleware_function)

//Function added with use() for a specific route
app.use('/someroute', a_middleware_function)

// A middleware function added for a specific HTTP verb and route
app.get('/', a_middleware_function )

app.listen(3000)

JavaScript提示:我們?cè)谏厦鎲为?dú)聲明中間件函數(shù),然后將其設(shè)置為回調(diào)。 在我們以前的路由處理函數(shù)中,我們?cè)谑褂没卣{(diào)函數(shù)時(shí)聲明了它。 在JavaScript中,兩種方法都是有效的。

Express文檔提供了許多關(guān)于使用 外部">寫 Express中間件。

提供靜態(tài)文件

express.static middleware to serve static files, including your images, CSS and JavaScript (static() is the only middleware function that is actually part of Express). For example, you would use the line below to serve images, CSS files, and JavaScript files from a directory named \'public\' at the same level as where you call node:\">

app.use(express.static('public'))

公共目錄中的任何文件通過將它們的文件名(相對(duì)添加到基本"public"目錄)添加到基本URL來服務(wù)。 例如:

http://localhost:3000/images/dog.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/about.html

您可以多次調(diào)用 static()來提供多個(gè)目錄。 如果一個(gè)文件不能被一個(gè)中間件函數(shù)找到,它將被簡(jiǎn)單地傳遞到后續(xù)的中間件(中間件被調(diào)用的順序是基于你的聲明順序)。

app.use(express.static('public'))
app.use(express.static('media'))

您還可以為靜態(tài)URL創(chuàng)建虛擬前綴,而不是將文件添加到基本URL。 例如,在這里,我們指定裝載路徑,以便加載文件 帶前綴"/ media":

app.use('/media', express.static('public'))

現(xiàn)在,您可以從 / media 路徑前綴加載 public 目錄中的文件。

http://localhost:3000/media/images/dog.jpg
http://localhost:3000/media/video/cat.mp4
http://localhost:3000/media/cry.mp3

有關(guān)詳細(xì)信息,請(qǐng)參閱在Express中提供靜態(tài)文件

處理錯(cuò)誤

錯(cuò)誤由一個(gè)或多個(gè)具有四個(gè)參數(shù)的特殊中間件函數(shù)處理,而不是通常的三個(gè):(err,req,res,next)。 例如:

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

這些可以返回任何所需的內(nèi)容,但必須在所有其他 app.use()之后調(diào)用,并路由調(diào)用,以便它們是請(qǐng)求處理過程中的最后一個(gè)中間件!

Express附帶一個(gè)內(nèi)置的錯(cuò)誤處理程序,它處理應(yīng)用程序中可能遇到的任何剩余錯(cuò)誤。 此默認(rèn)錯(cuò)誤處理中間件函數(shù)在中間件函數(shù)堆棧的末尾添加。 如果你向 next()傳遞錯(cuò)誤,并且你不在錯(cuò)誤處理程序中處理它,它將由內(nèi)置的錯(cuò)誤處理程序處理; 該錯(cuò)誤將被寫入具有堆棧跟蹤的客戶端。

注意:生產(chǎn)環(huán)境中不包括堆棧跟蹤。 要在生產(chǎn)模式下運(yùn)行它,您需要將環(huán)境變量 NODE_ENV 設(shè)置為\' production\'。

注意: HTTP404和其他"錯(cuò)誤"狀態(tài)代碼不會(huì)被視為錯(cuò)誤。 如果你想處理這些,你可以添加一個(gè)中間件函數(shù)來這樣做。 有關(guān)詳情,請(qǐng)參閱常見問題。

有關(guān)詳細(xì)信息,請(qǐng)參閱錯(cuò)誤處理(Express docs)。

使用數(shù)據(jù)庫

應(yīng)用程序可以使用 Node 支持的任何數(shù)據(jù)庫機(jī)制( Express 本身沒有定義數(shù)據(jù)庫管理的任何特定附加行為/要求)。 有很多選項(xiàng),包括PostgreSQL,MySQL,Redis,SQLite,MongoDB等。

為了使用這些,您必須首先使用NPM安裝數(shù)據(jù)庫驅(qū)動(dòng)程序。 例如,要為受歡迎的NoSQL MongoDB安裝驅(qū)動(dòng)程序,您可以使用以下命令:

$ npm install mongodb

數(shù)據(jù)庫本身可以在本地安裝或在云服務(wù)器上安裝。 在Express代碼中,您需要驅(qū)動(dòng)程序,連接到數(shù)據(jù)庫,然后執(zhí)行創(chuàng)建,讀取,更新和刪除(CRUD)操作。 下面的示例(從Express文檔)顯示如何使用MongoDB查找"哺乳動(dòng)物"記錄。

var MongoClient = require('mongodb').MongoClient

MongoClient.connect('mongodb://localhost:27017/animals', function (err, db) {
  if (err) throw err

  db.collection('mammals').find().toArray(function (err, result) {
    if (err) throw err

    console.log(result)
  })
})

另一種流行的方法是通過對(duì)象關(guān)系映射器("ORM")間接訪問您的數(shù)據(jù)庫。 在這種方法中,您將數(shù)據(jù)定義為"對(duì)象"或"模型",ORM將這些映射到底層數(shù)據(jù)庫格式。 這種方法有一個(gè)好處,作為開發(fā)人員,您可以繼續(xù)考慮JavaScript對(duì)象而不是數(shù)據(jù)庫語義,并且有一個(gè)明顯的地方執(zhí)行驗(yàn)證和檢查傳入數(shù)據(jù)。 我們將在后面的文章中更多地討論數(shù)據(jù)庫。

有關(guān)詳情,請(qǐng)參閱數(shù)據(jù)庫集成(Express docs)。

呈現(xiàn)數(shù)據(jù)(視圖)

模板引擎(通過Express 稱為"視圖引擎")允許您在模板中指定輸出文檔的結(jié)構(gòu),使用占位符來填充數(shù)據(jù) 當(dāng)頁面生成時(shí)。 模板通常用于創(chuàng)建HTML,但也可以創(chuàng)建其他類型的文檔。 Express支持一些模板引擎,并且有一個(gè)有用的比較 這里更受歡迎的引擎:比較JavaScript模板引擎:翡翠,小胡子,灰塵 和更多。

在您的應(yīng)用程序設(shè)置代碼中,您設(shè)置要使用的模板引擎以及Express使用\'views\'和\'view engines\'設(shè)置查找模板的位置,如下所示(您還必須安裝包含模板庫的包 !)

var express = require('express');
var app = express();

// Set directory to contain the templates ('views')
app.set('views', path.join(__dirname, 'views'));

// Set view engine to use, in this case 'some_template_engine_name'
app.set('view engine', 'some_template_engine_name');

模板的外觀將取決于您使用的引擎。 假設(shè)您有一個(gè)名為"index。< template_extension>"的模板文件 包含名為"title"和"message"的數(shù)據(jù)變量的占位符,您可以調(diào)用 "> Response.render() 在路由處理函數(shù)中創(chuàng)建和發(fā)送HTML響應(yīng):

app.get('/', function (req, res) {
  res.render('index', { title: 'About dogs', message: 'Dogs rock!' })
})

有關(guān)詳情,請(qǐng)參閱使用帶有Express的模板引擎(Express docs)。

文件結(jié)構(gòu)

Express對(duì)結(jié)構(gòu)或您使用的組件不做任何假設(shè)。 路由,視圖,靜態(tài)文件和其他特定于應(yīng)用程序的邏輯可以存在于任何目錄結(jié)構(gòu)的任意數(shù)量的文件中。 雖然完全有可能將整個(gè) Express 應(yīng)用程序放在一個(gè)文件中,但通常將應(yīng)用程序分成基于功能(例如帳戶管理,博客,討論板)和架構(gòu)問題域 例如模型,視圖或控制器(如果您正在使用 MVC體系結(jié)構(gòu)) >)。

在后面的主題中,我們將使用快速應(yīng)用程序生成器 ,它創(chuàng)建一個(gè)模塊化的應(yīng)用程序框架,我們可以輕松地?cái)U(kuò)展它來創(chuàng)建Web應(yīng)用程序。

    概要

    恭喜,您已完成Express / Node旅程中的第一步! 您現(xiàn)在應(yīng)該明白Express和Node的主要優(yōu)點(diǎn),以及Express應(yīng)用程序的主要部分(路由,中間件,錯(cuò)誤處理和模板代碼)。 你也應(yīng)該明白,Express是一個(gè)非主動(dòng)的框架,你把這些部分組合在一起的方式和你使用的庫大部分取決于你!

    當(dāng)然Express是一個(gè)非常輕量級(jí)的Web應(yīng)用程序框架,所以它的好處和潛力來自第三方庫和功能。 我們將在下面的文章中更詳細(xì)地討論這些。 在下一篇文章中,我們將介紹如何設(shè)置Node開發(fā)環(huán)境,以便您可以開始看到一些Express代碼在運(yùn)行。

    也可以看看

    以上內(nèi)容是否對(duì)您有幫助:
    在線筆記
    App下載
    App下載

    掃描二維碼

    下載編程獅App

    公眾號(hào)
    微信公眾號(hào)

    編程獅公眾號(hào)