Node.js的Express框架入门

Node.js的Express框架入门

什么是Node?

Node(正式名称 Node.js)是一个开源的、跨平台的运行时环境,有了它,开发人员可以使用 JavaScript 创建各种服务器端工具和应用程序。此运行时主要用于浏览器上下文之外(即可以直接运行于计算机或服务器操作系统上)。据此,该环境省略了一些浏览器专用的 JavaScript API,同时添加了对更传统的 OS API(比如 HTTP 库和文件系统库)的支持

Hello Node.js

以下示例将创建一个 web 服务器,它将监听对 URL http://127.0.0.1:8000/ 所有种类的 HTTP 请求,当接收到一个请求时,脚本将做出响应:返回一个字符串“Hello World”。如果已经安装了 Node,可以按照下面的步骤尝试一下:

1.打开一个空文件夹

2.在Visual Studio Code中创建一个**“hello.js”**的文件,把以下代码粘贴进来。

// 调用 HTTP 模块
const http = require("http");

// 创建 HTTP 服务器并监听 8000 端口的所有请求
http
  .createServer((request, response) => {
    // 用 HTTP 状态码和内容类型来设定 HTTP 响应头
    response.writeHead(200, { "Content-Type": "text/plain" });

    // 发送响应体 "Hello World"
    response.end("Hello World\n");
  })
  .listen(8000);

// 在控制台打印访问服务器的 URL
console.log("服务器运行于 http://127.0.0.1:8000/ 或者http://localhost:8000/");

4.打开终端输入node hello.js

5.在终端打印服务器运行于 http://127.0.0.1:8000/ 或者http://localhost:8000/

6.在浏览器地址栏中输入 http://127.0.0.1:8000/ 或者http://localhost:8000/并回车,可以看到网页左上角有"hello world"字样。

hello woed

Web 框架

Node 本身并不支持其他常见的 web 开发任务。如果需要进行一些具体的处理,比如运行其他 HTTP 动词(比如 GETPOSTDELETE 等)、分别处理不同 URL 路径的请求(“路由”)、托管静态文件,或用模板来动态创建响应,那么可能就要自己编写代码了,亦或使用 web 框架,以避免重新发明轮子。

什么是Express框架?

Express 是一个基于 Node.js 平台的快速、无开销且极简的 web 开发框架,它提供了一系列强大的特性来帮助你构建 web 应用和 API。Express 使用 JavaScript 编写,运行在 Node.js 环境中,这意味着你可以使用 JavaScript 来编写整个应用,包括前端和后端。

Hello world Express

如果你已经安装了 Node 和 Express

1.打开一个空文件夹

2.在Visual Studio Code中打开终端创建package.json配置文件

npm init   // 输入指令后,创建package.json文件,并进行基本信息设置(可一直回车)

3.安装express框架

npm i express

4.创建一个app.js文件,把以下代码复制进去

//在index.js文件中通过require导入express模块
const express = require("express");
//创建express实例对象app
const app = express();
//通过app.post创建一个post方法的请求,请求地址为:/
//第一个参数是请求地址,第二个是回调函数,回调函数有两个参数,req:请求功能对象,res:响应功能对象
app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(3000, () => {
  console.log("服务器开启成功,请访问 localhost:3000");
});
//服务启动成功,在控制台输出 "服务器开启成功,请访问 localhost:3000"

前两行通过 require() 导入 Express 模块,并创建了一个 Express 应用。传统上把这个对象命名为 app,它可以进行路由 HTTP 请求、配置中间件、渲染 HTML 视图、注册模板引擎以及修改 应用程序设置 等操作,从而控制应用的行为(例如,环境模式,路由定义是否为区分大小写等)。

代码的中间部分(从 app.get() 开始共三行)是路由定义app.get() 方法指定了一个回调(callback)函数,该函数在每监听到一个关于站点根目录路径('/')的 HTTP GET 请求时调用。此回调函数以一个请求和一个响应对象作为参数,并直接调用响应的 send() 来返回字符串“Hello World!”

最后一个代码块在“3000”端口上启动服务器,并在控制台打印日志。服务器运行时,可用浏览器访问 localhost:3000,看看响应返回了什么。

使用异步API

JavaScript 代码在完成那些需要一段时间才能完成的操作时,经常会用异步 API 来取代同步 API。同步 API 下,每个操作完成后才可以进行下一个操作。例如,下列日志函数是同步的,将按顺序将文本打印到控制台(第一、第二)。

console.log("第一");
console.log("第二");

而异步 API 下,一个操作开始后(在其完成之前)会立即返回。一旦操作完成,API 将使用某种机制来执行附加操作。例如,下面的代码将打印“第二、第一”。这是因为虽然先调用了 setTimeout() 方法并立即返回,但它的操作到 3 秒后才完成。

setTimeout(() => {
  console.log("第一");
}, 3000);
console.log("第二");

在 Node 中使用无阻塞异步 API 甚至比在浏览器中更为重要,这是因为 Node 是一个单线程事件驱动的执行环境。“单线程”意味着对服务器的所有请求运行在同一个线程上,而不是分布在不同的进程上。这个模式在速度和管理服务器资源方面效率很高,但也意味着如果以同步方式调用的函数占用了很长时间,不仅会阻塞当前请求,还会阻塞当前 web 应用其他所有请求。

有多种方法可以让一个异步 API 通知当前应用它已执行完毕。最常用的是在调用异步 API 时注册一个回调函数,在 API 操作结束后将“回调”之。这也是上面的代码所使用的方法。

备注: 如果有一系列独立的异步操作必须按顺序执行,那么使用回调可能会非常“混乱”,因为这会导致多级嵌套回调。人们通常把这个问题叫做“回调地狱”。缓解这个问题有以下办法:良好的编码实践(参考 http://callbackhell.com/)、使用 async 等模块、迁移至 ES6 并使用 Promise 等特性。

创建路由处理器

上文的 Hello World 示例中定义了一个(回调)路由处理函数来处理对站点根目录('/')的 HTTP GET 请求。

app.get("/", (req, res) => {
  res.send("Hello World!");
});

回调函数将请求和响应对象作为参数。该函数直接调用响应的 send() 以返回字符串“Hello World!”。有 许多其他响应方法 可以结束请求/响应周期,例如,通过调用 res.json() 来发送 JSON 响应、调用 res.sendFile() 来发送文件。

Express 应用对象还提供了为其他所有 HTTP 动词定义路由处理器的方法,大多数处理器的使用方式完全一致:

checkout(), copy(), delete(), get(), head(), lock(), merge(), mkactivity(), mkcol(), move(), m-search(), notify(), options(), patch(), post(), purge(), put(), report(), search(), subscribe(), trace(), unlock(), unsubscribe().

有一个特殊的路由方法 app.all(),它可以在响应任意 HTTP 方法时调用。用于在特定路径上为所有请求方法加载中间件函数。以下示例(来自 Express 文档)中的处理程序将在监听到针对 /secret 的任意 HTTP 动词(只要 HTTP 模块 支持)的请求后执行。

app.all("/secret", (req, res, next) => {
  console.log("访问私有文件 ...");
  next(); // 控制权传递给下一个处理器
});

使用中间件

中间件在 Express 应用中得到了广泛使用,从提供错误处理静态文件、到压缩 HTTP 响应等等。路由函数可以通过向 HTTP 客户端返回一些响应来结束 HTTP“请求 - 响应”周期,而中间件函数通常是对请求或响应执行某些操作,然后调用“栈”里的下一个函数,可能是其他中间件或路由处理器。中间件的调用顺序由应用开发者决定。

const express = require("express");
const app = express();

// 示例中间件函数
const a_middleware_function = (req, res, next) => {
  // ... 进行一些操作
  next(); // 调用 next() ,Express 将调用处理链中下一个中间件函数。
};

// 用 use() 为所有的路由和动词添加该函数
app.use(a_middleware_function);

// 用 use() 为一个特定的路由添加该函数
app.use("/someroute", a_middleware_function);

// 为一个特定的 HTTP 动词和路由添加该函数
app.get("/", a_middleware_function);

app.listen(3000);

托管静态文件

可以使用 express.static 中间件来托管静态文件,包括图片、CSS 以及 JavaScript 文件(其实 static() 是 Express 提供的原生中间件函数之一)。例如,可以通过下面一行来托管 ‘public’ 文件夹(应位于 Node 调用的同一级)中的文件:

app.use(express.static("public"));

现在 ‘public’ 文件夹下的所有文件均可通过在根 URL 后直接添加文件名来访问了,比如:

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

可以通过多次调用 static() 来托管多个文件夹。如果一个中间件函数找不到某个文件,将直接传递给下一个中间件(中间件的调用顺序取决于声明顺序)。

app.use(express.static("public"));
app.use(express.static("media"));

还可以为静态 URL 创建一个虚拟的前缀,而不是直接把文件添加到根 URL 里。比如,这里 指定了一个装载路径,于是这些文件将通过 ‘/media’ 前缀调用:

app.use("/media", express.static("public"));

现在可以通过 ‘/media’ 路径前缀来访问 ‘public’ 文件夹中的文件。

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

错误处理

用来处理错误的特殊中间件函数有四个参数(err, req, res, next),而不是之前的三个。例如:

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send("出错了!");
});

小结

恭喜,你迈出了 Express/Node 旅程的第一步!你现在已经了解了 Express 与 Node 的主要优势,并大致了解了 Express 应用的结构 (路由处理器、中间件、错误处理和模板代码)。你还了解到 Express 作为一个高度包容的框架,让你在组织应用结构和库时更自由,更开放!

诚然,Express 是一个非常轻量的 web 应用框架,这是有意为之的,它巨大的裨益和无尽的潜能都来自第三方的库和功能。今后的章节会详细讨论。下一节会讲如何设置 Node 开发环境,之后就能开始 Express 的实战了。

你可能感兴趣的:(node.js,express,学习,javascript)