一、express框架的基本使用
Express框架是Node.js中最受欢迎的web开发框架,它的设计简洁而且功能强大,有着大量的插件和社区支持。
基于Express使用Node.js创建web应用的基本步骤如下:
- 首先你需要安装Node.js和npm(Node包管理器),然后在你的项目文件夹中安装Express:
npm install express --save
- 然后在项目中创建一个JavaScript文件,比如app.js,并且在文件中导入Express:
var express = require('express');
var app = express();
- 使用app对象的get方法,对某个URL路径进行路由处理:
app.get('/', function (req, res) {
res.send('Hello World!');
});
这个代码表示当客户端向服务器发起一个HTTP GET请求,请求的URL路径为“/”时,服务器会响应一个“Hello World!”的消息。
- 使用app对象的listen方法,让服务器开始监听某个端口:
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
这个代码表示服务器会在3000端口监听请求。
- 运行这个Node.js应用:
node app.js
然后你可以打开浏览器或者用postman等工具访问 http://localhost:3000,就会看到显示的“Hello World!”消息。
完整代码如下:
// 引入express
var express = require('express');
// 创建express实例
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
// 监听3000端口
app.listen(3000, function () {
console.log('app is listening at port 3000');
console.log('http://localhost:3000');
});
Express还有很多高级特性,比如可以方便地解析请求参数、处理POST请求、使用模板引擎生成动态HTML页面、使用中间件进行统一处理等等。
二、解析get/post请求
1. 接收get请求参数
如果我们要接收GET请求的参数,我们可以通过req.query
对象来获取。比如有一个GET请求参数是http://localhost:3000/?name=John
,我们就可以通过以下方式获取到参数name的值:
app.get('/', (req, res) => {
let name = req.query.name;
res.send(`Hello ${name}`);
});
在这里,当用户访问http://localhost:3000/?name=John
时,应用将会返回字符串"Hello John"。
2. 接收post请求参数
在node.js中,我们通常使用Express框架来处理HTTP请求。对于POST请求,Express提供了专门的API。下面是一个基本示例:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json()); // 在请求处理之前,先解析JSON
app.post('/example', (req, res) => {
console.log(req.body); // 打印输出请求的JSON数据
res.send('Post request received');
});
app.listen(3000, () => console.log('Server started on port 3000'));
以上代码创建了一个Express服务器,并监听3000端口,然后使用body-parser
中间件来解析JSON格式的POST请求。bodyParser.json()
返回的是一个用于处理HTTP请求的函数,每当有新的请求过来,这个函数就会被调用,它会读取请求体中的JSON数据,然后放到req.body
中。
当/example
路径接收到POST请求时,Express会执行对应的回调函数,打印出解析后的JSON数据,然后将Post request received
返回给客户端。
如果你想接收不同格式的POST请求参数,比如从表单提交的数据,你需要使用不同的body-parser
解析器。例如,可以使用bodyParser.urlencoded()
解析"application/x-www-form-urlencoded" 格式的数据:
app.use(bodyParser.urlencoded({ extended: true }));
extended
选项设置为true
意味着用更复杂的库(querystring库)来解析URL编码的数据,这样可以解析更复杂的对象、嵌套对象等等。
如果POST请求发送的是纯文本或其他格式,可以使用bodyParser.text()
或bodyParser.raw()
来处理。
总的来说,body-parser
中间件提供了一系列方法来解析不同格式的POST请求数据,根据你的需要选择使用即可。
请注意,Express 4.16.0增加了一些内置的中间件,所以对于基本的json和urlencoded解析,你可以不用body-parser
。
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
例如:
// 引入express
const express = require('express');
// 创建express实例
const app = express();
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {
let name = req.query.name;
res.send(`Hello ${name}`);
});
app.post('/', (req, res) => {
let user = req.body;
res.send(user);
});
// 监听3000端口
app.listen(3000, function () {
console.log('app is listening at port 3000');
console.log('http://localhost:3000');
});
-
application/x-www-form-urlencoded
-
application/json
三、处理回调地狱问题
1. 内置模块util介绍
util
是Node.js的核心模块之一,在Node中,可通过 require('util')
命令将其引入。
util
模块主要用于支持Node.js核心API的需要,尽管一些实用函数可供应用程序和其它模块使用。以下是util
模块中一些常用的函数:
util.debuglog
: 创建一个函数,基于NODE_DEBUG环境变量,用于创建一个条件性的调试器。util.deprecate
: 将一个函数包装成废弃函数。util.format
: 返回一个格式化的字符串。util.inherits
: 实现对象间原型继承的函数。util.inspect
: 将任意对象转换为字符串,通常用于调试和错误输出。util.isArray
:如果给定的参数 “object” 是一个数组返回true,否则返回false。util.isDate
: 如果给定的参数 “object” 是一个日期返回true,否则返回false。util.isError
: 如果给定的参数 “object” 是一个错误对象返回true,否则返回false。util.isRegExp
: 如果给定的参数 “object” 是一个正则表达式返回true,否则返回false。
注意,在Node.js v10.0.0中,一些函数(例如 util.isError
, util.isDate
等)已经被废弃,建议使用更标准的JavaScript内置API,如 Array.isArray
,instanceof Date
等来替换。
2. promisify的使用
util.promisify
是 Node.js 的内置模块中的一个方法,它主要把一个遵循通用错误优先的回调风格的函数(即最后一个参数是一个 (err, value) => ...
回调)转换成一个返回 promise 的函数。
示例如下:
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
readFile('/some/file')
.then(data => {
console.log(data);
})
.catch(err => {
console.log(err);
});
在这个示例中,fs.readFile
是一个典型的 Node.js 回调风格的函数,它的最后一个参数为回调函数,回调函数的第一个参数为可能出现的错误,第二个参数为函数的返回值。
通过 util.promisify
,我们将它转换成了一个返回 promise 的函数。这样,我们就可以使用 .then
和 .catch
来处理函数的返回值和可能出现的错误,而不需要通过回调函数的方式。这通常可以让代码更加简洁,逻辑更清晰。
实际应用场景
在实际编程中,比如你正在使用一款第三方库,而这个第三方库的 API 是 callback 风格的。你想在 async/await 的语境下使用这个 API。那么,util.promisify 就可以帮助你将这个 API 转换成 Promise 风格,从而可以在 async/await 中使用。
例如:
const util = require('util');
const request = require('request');
const requestPromise = util.promisify(request);
async function main() {
const { body } = await requestPromise('https://example.com');
console.log(body); // 请求返回的 HTML
}
main();
在这个例子中,request
函数源自一个 HTTP 请求库,该函数符合错误优先回调风格。通过 util.promisify
,我们将 request
函数转换成返回 promise 的函数,然后在 async/await 的上下文中使用它。这使我们能以同步的方式编写异步代码,使处理异步代码变得更简单。
四、HTTP响应状态码介绍
HTTP响应状态码,或HTTP状态码,是服务器在响应HTTP请求时返回的一个3位数字代码,用于表示服务器处理请求的结果。这些代码被分类为五种类别,以它们的首位数字表示,例如1xx,2xx,3xx,4xx和5xx。
1. 1xx(信息响应)
指示请求已收到,继续处理。
例如:
- 100(继续):客户端应继续其请求
- 101(切换协议):根据客户端的要求,服务器会切换协议。
2. 2xx(成功)
表明请求已被成功接收,理解,和接受。
例如:
- 200(成功):请求成功
- 201(已创建):请求成功并且服务器创建了新的资源
- 202(已接受):服务器已接受请求,但尚未处理
3. 3xx(重定向)
需要客户端采取进一步的操作才能完成请求。
例如:
- 300(多种选择):针对资源有多个配置可用,需要用户选择其中一个。
- 301(永久移动):请求的网页已永久移动到新位置
- 302(临时移动):服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
4. 4xx(请求错误)
表示请求包含语法错误或无法完成请求。
例如:
- 400(错误请求):服务器无法理解请求的格式
- 401(未授权):用户需要身份验证
- 403(禁止):服务器理解请求客户端的请求,但是拒绝执行它。
- 404(未找到):服务器找不到请求的网页。
5. 5xx(服务器错误)
表示服务器在尝试处理请求时发生内部错误。
例如:
- 500(服务器内部错误):服务器遇到错误,无法完成请求
- 502(错误网关):服务器作为网关或代理,从上游服务器收到无效响应。
- 503(服务不可用):服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。
- 504(网关超时):服务器作为网关或代理,但是没有及时从上游服务器收到请求。
表格形式
状态码 | 含义 | 描述 |
---|---|---|
100 | 继续 | 客户端应当继续发送请求。 |
101 | 切换协议 | 服务器根据客户端的请求切换协议。 |
200 | OK | 请求成功。一般用于GET与POST请求。 |
201 | 已创建 | 请求成功并且服务器创建了新的资源。 |
202 | 接受 | 已接受请求,但未处理完成。 |
203 | 非授权信息 | 请求成功,但返回的元信息不在原始服务器上,而是从一个副本返回的。 |
204 | 无内容 | 服务器成功处理,但未返回内容。 |
205 | 重置内容 | 服务器处理成功,用户终端(例如:浏览器)应重置文档视图。 |
206 | 部分内容 | 服务器成功处理了部分GET请求。 |
300 | 多种选择 | 请求的资源可包含多个位置,可用于自动选择服务器。 |
301 | 永久移动 | 请求的资源被永久的移动到新URI,返回信息会包括新的URI。 |
302 | 临时移动 | 与301类似,但资源只是临时被移动。 |
303 | 查看其他位置 | 请求对应的资源存在着另一个URI,应使用GET方法获取该资源。 |
304 | 未修改 | 资源未改变。 |
305 | 使用代理 | 被请求的资源必须通过指定的代理获取。 |
306 | 已经废弃 | 在以前版本的HTTP中使用。 |
307 | 临时重定向 | 与302类似,但对于POST请求,会跳转到新的URI并使用GET方法。 |
400 | 错误请求 | 请求中有语法问题,或不能满足请求。 |
401 | 未授权 | 需要证明身份。 |
402 | 需要付款 | 预留的响应,目前未被使用。 |
403 | 被禁止访问 | 服务器拒绝请求。 |
404 | 找不到 | 无法找到所请求的资源。 |
405 | 不允许的方法 | 请求中的方法被禁止。 |
406 | 不可接受 | 服务器只能生成客户端不接受的响应。 |
407 | 需要代理验证 | 客户端必须通过代理授权。 |
408 | 请求超时 | 服务器等待请求超时。 |
409 | 冲突 | 服务器在满足请求时发现冲突。 |
410 | 过期 | 请求的资源已经不存在。 |
411 | 需要长度 | 服务器无法处理不包含Content-Length的请求信息。 |
412 | 未满足前提条件 | 服务器未满足客户端在请求中设置的其中一个前提条件。 |
413 | 请求实体过大 | 请求的实体过大,服务器无法处理。 |
414 | 请求URI过长 | 请求URI过长,服务器无法处理。 |
415 | 不支持媒体类型 | 请求的格式不受请求页面的支持。 |
416 | 请求范围不满足 | 请求中包含的Range头字段不能与响应中的实体兼容。 |
417 | 未满足期望 | 服务器不能满足Expect头字段指定的预期。 |
500 | 服务器内部错误 | 服务器遇到了一个未曾预料的状况,导致不能完成客户端请求。 |
501 | 未实现 | 服务器不支持当前请求所需要的某个功能。 |
502 | 错误网关 | 当作为一个代理或者网关时,处理其他服务器的响应失败。 |
503 | 服务器目前无法使用 | 由于过载或者维护,服务器暂时无法处理请求。 |
504 | 网关超时 | 作为一个网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器收到响应。 |
505 | HTTP版本不支持 | 服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本。 |
以上,就是HTTP响应状态码的基本信息。在软件开发过程中,了解并正确使用这些状态码,有助于增强应用程序的健壮性和可靠性。