Node.js心得笔记

npm init 可用npm 来调试node项目

浏览器中的顶级对象时window

javascript 复制代码
<ref *1> Object [global] { global: [Circular *1], clearImmediate: [Function: clearImmediate], setImmediate: [Function: setImmediate] { [Symbol(nodejs.util.promisify.custom)]: [Getter] }, clearInterval: [Function: clearInterval], clearTimeout: [Function: clearTimeout], setInterval: [Function: setInterval], setTimeout: [Function: setTimeout] { [Symbol(nodejs.util.promisify.custom)]: [Getter] }, queueMicrotask: [Function: queueMicrotask], structuredClone: [Function: structuredClone], atob: [Getter/Setter], btoa: [Getter/Setter], performance: [Getter/Setter], fetch: [Function: fetch], crypto: [Getter] }

node中的顶级对象时global

module.exports 与 require

复制代码

const GetName = ()=>{ return "jack" ; }; const GetAge = ()=>{ return 18; }; module.exports = { GetName, GetAge }

复制代码

const {GetName,GetAge} = require("./utils"); GetName(); GetAge();

默认情况下,Node.js 将 JavaScript 文件视为 CommonJS 模块,需要使用:module.exports ={} 和 require 来导出导入。 若使用export 与 import 报错,需要将package.js 中的:"type": "commonjs" , 转成type": "module"

export default = methods 更适用于单个组件进行导出,可以随意命名,并且一个js文件中只能有一个默认导出

export = {...methods} 更适用于多个方法的导出,不能随意命名,但可以通过 import {methodName as methodSetName} 来进行命名,一个js文件中可有多个普通导出

值得注意的是,在一个js文件中,可以同时有多个普通导出与一个默认导出。

后端server配置CORS ,允许前端跨域发起请求

同源策略是一个安全机制,要求"协议+域名+端口"三者相同,否则浏览器会阻止网页向不同源的服务器发送请求。

复制代码

// Add CORS headers,允许跨域 res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5173'); //'http://localhost:5173/' 会报错,不能加,因为这个CORS是根据字符串来匹配的 // 允许所有源 res.setHeader('Access-Control-Allow-Origin', '*'); // 也可以根据请求源动态设置,允许信任的请求源 const allowedOrigins = ['http://localhost:5173', 'https://yourapp.com', 'http://127.0.0.1:8080']; const origin = req.headers.origin; if (allowedOrigins.includes(origin)) { res.setHeader('Access-Control-Allow-Origin', origin); } res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');

若前端在请求头中自定义了某个属性,你需要在后台服务器中的CORS也定义上:

复制代码

//前端 axios.get('http://localhost:8888/', { headers: { 'X-Custom-Header': 'foobar' } }) //后台服务器 res.setHeader('Access-Control-Allow-Headers','Content-Type, Authorization, X-Custom-Header');

避免修改一次代码就要重启一次服务器

复制代码

npm install nodemon

package-lock.js 是依赖项文件夹,类似于python中的requirement.txt,执行npm install 可下载所有的依赖项。并会将所有的依赖项存储到文件夹node_modules里。同时,npm i 也能完成更新依赖包的作用。作用是为了防止将依赖包都放到github上

也可以在.gitignore中添加不推送到github中的文件夹/文件名

复制代码

.gitignore | node_modules | ...all_requirement_packages

配置package.json文件,完成使用nodemon 来调试程序。

复制代码

"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "nodemon server.js", "dev": "nodemon server.js" },

. env 文件

用于设置项目中的全局变量,不能有空格

复制代码

PORT=8080

复制代码

//实际使用 const PORT = process.env.PORT;

复制代码

"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "nodemon server.js", "dev": "nodemon --env-file=.env server.js" },

必须要加 --env-file=.env,否则指定的全局变量会显示undefined

并且可以在.gitignore文件中,添加.env ,防止上传到git

原生的node.js服务端

复制代码

import http from 'http'; // const PORT = process.end.PORT; const PORT = process.env.PORT; const server = http.createServer((req, res) => { // Add CORS headers,解决跨域问题 res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5173'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Custom-Header'); //debug console.log(req.url); //客户端请求的网址 console.log(req.method); //客户端的请求方式 // For normal requests, proceed with your existing code res.writeHead(200, "OK", { 'Content-Type': 'text/html' }); res.write( `<h1>hello user</h1> <h2>Welcome to http my server</h2> <h3>Wish you have a good day</h3> ` ); res.end(JSON.stringify({ "message": "ok", "statusCode": 200, "data": { "name": "Jack", "age": 18, "home":"ShangHai", } })); }); server.listen(PORT, () => { console.log(`use ${PORT} port ,search: http://localhost:${PORT}/`); });

客户端像后端发起get请求,为什么后台打印:OPTIONS GET

这是由于:CORS预检机制

当浏览器发起跨域请求时,会触发CORS(跨源资源共享)机制。在特定情况下,浏览器会在实际请求前自动发送一个"预检请求"(OPTIONS请求),这就是您在后台看到OPTIONS和GET两个请求的原因。

关于Access-Control-Max-Age的详细说明

这个头部信息的作用是告诉浏览器在指定的时间内(以秒为单位)可以缓存预检请求的结果,而无需再次发送OPTIONS请求。这对于优化性能非常有益,特别是在频繁发生跨域请求的应用中。

浏览器限制:不同浏览器对Access-Control-Max-Age的最大值有不同限制:

  • Chrome: 最大值为7200秒(2小时)

  • Firefox: 最大值为86400秒(24小时)

  • Safari: 没有明确限制,但遵循标准建议

将获取当前文件的路径

复制代码

import fs from 'fs/promises'; import url from 'url'; import path from 'path'; //get current path //import.meta.url 当前路径的url export const GetCurrentPath = (importUrl) =>{ const fileName = url.fileURLToPath(importUrl); //将文件的url转化为路径 const dirName = path.dirname(fileName); //输入:文件的路径;输出:文件所在目录 return { fileName, dirName } } console.log(import.meta.url); //file:///C:/Users/32217/Desktop/%E9%A1%B9%E7%9B%AE/%E5%8C%BB%E7%96%97%E5%81%A5%E5%BA%B7%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F/code/front-end/server.js console.log(fileName); console.log(dirName); /* C:\Users\32217\Desktop\项目\医疗健康管理系统\code\front-end\server.js C:\Users\32217\Desktop\项目\医疗健康管理系统\code\front-end */

response.writeHead() 与 response.end() 必须配套使用,否则会响应超时!!!

Request

复制代码

C:\Users\32217\Desktop\项目\医疗健康管理系统\code\front-end\public\404.html Using port 8888, visit: http://localhost:8888/ req.url:/Login req.method:POST <ref *2> IncomingMessage { _events: { close: undefined, error: undefined, data: undefined, end: undefined, readable: undefined }, _readableState: ReadableState { highWaterMark: 16384, buffer: [], bufferIndex: 0, length: 0, pipes: [], awaitDrainWriters: null, [Symbol(kState)]: 1315084 }, _maxListeners: undefined, socket: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _closeAfterHandlingError: false, _events: { close: [Array], error: [Function: socketOnError], prefinish: undefined, finish: undefined, drain: [Function: bound socketOnDrain], data: [Function: bound socketOnData], end: [Array], readable: undefined, timeout: [Function: socketOnTimeout], resume: [Function: onSocketResume], pause: [Function: onSocketPause] }, _readableState: ReadableState { highWaterMark: 16384, buffer: [], bufferIndex: 0, length: 0, pipes: [], awaitDrainWriters: null, [Symbol(kState)]: 193997060 }, _writableState: WritableState { highWaterMark: 16384, length: 0, corked: 0, onwrite: [Function: bound onwrite], writelen: 0, bufferedIndex: 0, pendingcb: 0, [Symbol(kState)]: 17564420, [Symbol(kBufferedValue)]: null }, allowHalfOpen: true, _maxListeners: undefined, _eventsCount: 8, _sockname: null, _pendingData: null, _pendingEncoding: '', server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, requestTimeout: 300000, headersTimeout: 60000, keepAliveTimeout: 5000, connectionsCheckingInterval: 30000, requireHostHeader: true, joinDuplicateHeaders: undefined, rejectNonStandardBodyWrites: false, _events: [Object: null prototype], _eventsCount: 3, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, _listeningId: 2, allowHalfOpen: true, pauseOnConnect: false, noDelay: true, keepAlive: false, keepAliveInitialDelay: 0, highWaterMark: 16384, httpAllowHalfOpen: false, timeout: 0, maxHeadersCount: null, maxRequestsPerSocket: 0, _connectionKey: '6::::8888', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 245, [Symbol(kUniqueHeaders)]: null, [Symbol(http.server.connections)]: ConnectionsList {}, [Symbol(http.server.connectionsCheckingInterval)]: Timeout { _idleTimeout: 30000, _idlePrev: [TimersList], _idleNext: [TimersList], _idleStart: 191, _onTimeout: [Function: bound checkConnections], _timerArgs: undefined, _repeat: 30000, _destroyed: false, [Symbol(refed)]: false, [Symbol(kHasPrimitive)]: false, [Symbol(asyncId)]: 248, [Symbol(triggerId)]: 246 } }, _server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, requestTimeout: 300000, headersTimeout: 60000, keepAliveTimeout: 5000, connectionsCheckingInterval: 30000, requireHostHeader: true, joinDuplicateHeaders: undefined, rejectNonStandardBodyWrites: false, _events: [Object: null prototype], _eventsCount: 3, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, _listeningId: 2, allowHalfOpen: true, pauseOnConnect: false, noDelay: true, keepAlive: false, keepAliveInitialDelay: 0, highWaterMark: 16384, httpAllowHalfOpen: false, timeout: 0, maxHeadersCount: null, maxRequestsPerSocket: 0, _connectionKey: '6::::8888', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 245, [Symbol(kUniqueHeaders)]: null, [Symbol(http.server.connections)]: ConnectionsList {}, [Symbol(http.server.connectionsCheckingInterval)]: Timeout { _idleTimeout: 30000, _idlePrev: [TimersList], _idleNext: [TimersList], _idleStart: 191, _onTimeout: [Function: bound checkConnections], _timerArgs: undefined, _repeat: 30000, _destroyed: false, [Symbol(refed)]: false, [Symbol(kHasPrimitive)]: false, [Symbol(asyncId)]: 248, [Symbol(triggerId)]: 246 } }, parser: HTTPParser { '0': null, '1': [Function: parserOnHeaders], '2': [Function: parserOnHeadersComplete], '3': [Function: parserOnBody], '4': [Function: parserOnMessageComplete], '5': [Function: bound onParserExecute], '6': [Function: bound onParserTimeout], _headers: [], _url: '', socket: [Circular *1], incoming: [Circular *2], outgoing: null, maxHeaderPairs: 2000, _consumed: true, onIncoming: [Function: bound parserOnIncoming], joinDuplicateHeaders: null, [Symbol(resource_symbol)]: [HTTPServerAsyncResource] }, on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], setEncoding: [Function: socketSetEncoding], _paused: false, _httpMessage: ServerResponse { _events: [Object: null prototype], _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, strictContentLength: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, _closed: false, socket: [Circular *1], _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], req: [Circular *2], _sent100: false, _expect_continue: false, _maxRequestsPerSocket: 0, [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(kBytesWritten)]: 0, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype], [Symbol(errored)]: null, [Symbol(kHighWaterMark)]: 16384, [Symbol(kRejectNonStandardBodyWrites)]: false, [Symbol(kUniqueHeaders)]: null }, [Symbol(async_id_symbol)]: 250, [Symbol(kHandle)]: TCP { reading: true, onconnection: null, _consumed: true, [Symbol(owner_symbol)]: [Circular *1] }, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(shapeMode)]: true, [Symbol(kCapture)]: false, [Symbol(kSetNoDelay)]: true, [Symbol(kSetKeepAlive)]: false, [Symbol(kSetKeepAliveInitialDelay)]: 0, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0 }, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: false, rawHeaders: [ 'Host', 'localhost:8888', 'Connection', 'keep-alive', 'Content-Length', '45', 'sec-ch-ua-platform', '"Windows"', 'User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', 'Accept', 'application/json, text/plain, */*', 'sec-ch-ua', '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"', 'Content-Type', 'application/json', 'X-Custom-Header', 'foobar', 'sec-ch-ua-mobile', '?0', 'Origin', 'http://localhost:5173', 'Sec-Fetch-Site', 'same-site', 'Sec-Fetch-Mode', 'cors', 'Sec-Fetch-Dest', 'empty', 'Referer', 'http://localhost:5173/', 'Accept-Encoding', 'gzip, deflate, br, zstd', 'Accept-Language', 'zh-CN,zh;q=0.9' ], rawTrailers: [], joinDuplicateHeaders: null, aborted: false, upgrade: false, url: '/Login', method: 'POST', statusCode: null, statusMessage: null, client: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _closeAfterHandlingError: false, _events: { close: [Array], error: [Function: socketOnError], prefinish: undefined, finish: undefined, drain: [Function: bound socketOnDrain], data: [Function: bound socketOnData], end: [Array], readable: undefined, timeout: [Function: socketOnTimeout], resume: [Function: onSocketResume], pause: [Function: onSocketPause] }, _readableState: ReadableState { highWaterMark: 16384, buffer: [], bufferIndex: 0, length: 0, pipes: [], awaitDrainWriters: null, [Symbol(kState)]: 193997060 }, _writableState: WritableState { highWaterMark: 16384, length: 0, corked: 0, onwrite: [Function: bound onwrite], writelen: 0, bufferedIndex: 0, pendingcb: 0, [Symbol(kState)]: 17564420, [Symbol(kBufferedValue)]: null }, allowHalfOpen: true, _maxListeners: undefined, _eventsCount: 8, _sockname: null, _pendingData: null, _pendingEncoding: '', server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, requestTimeout: 300000, headersTimeout: 60000, keepAliveTimeout: 5000, connectionsCheckingInterval: 30000, requireHostHeader: true, joinDuplicateHeaders: undefined, rejectNonStandardBodyWrites: false, _events: [Object: null prototype], _eventsCount: 3, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, _listeningId: 2, allowHalfOpen: true, pauseOnConnect: false, noDelay: true, keepAlive: false, keepAliveInitialDelay: 0, highWaterMark: 16384, httpAllowHalfOpen: false, timeout: 0, maxHeadersCount: null, maxRequestsPerSocket: 0, _connectionKey: '6::::8888', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 245, [Symbol(kUniqueHeaders)]: null, [Symbol(http.server.connections)]: ConnectionsList {}, [Symbol(http.server.connectionsCheckingInterval)]: Timeout { _idleTimeout: 30000, _idlePrev: [TimersList], _idleNext: [TimersList], _idleStart: 191, _onTimeout: [Function: bound checkConnections], _timerArgs: undefined, _repeat: 30000, _destroyed: false, [Symbol(refed)]: false, [Symbol(kHasPrimitive)]: false, [Symbol(asyncId)]: 248, [Symbol(triggerId)]: 246 } }, _server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, requestTimeout: 300000, headersTimeout: 60000, keepAliveTimeout: 5000, connectionsCheckingInterval: 30000, requireHostHeader: true, joinDuplicateHeaders: undefined, rejectNonStandardBodyWrites: false, _events: [Object: null prototype], _eventsCount: 3, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, _listeningId: 2, allowHalfOpen: true, pauseOnConnect: false, noDelay: true, keepAlive: false, keepAliveInitialDelay: 0, highWaterMark: 16384, httpAllowHalfOpen: false, timeout: 0, maxHeadersCount: null, maxRequestsPerSocket: 0, _connectionKey: '6::::8888', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 245, [Symbol(kUniqueHeaders)]: null, [Symbol(http.server.connections)]: ConnectionsList {}, [Symbol(http.server.connectionsCheckingInterval)]: Timeout { _idleTimeout: 30000, _idlePrev: [TimersList], _idleNext: [TimersList], _idleStart: 191, _onTimeout: [Function: bound checkConnections], _timerArgs: undefined, _repeat: 30000, _destroyed: false, [Symbol(refed)]: false, [Symbol(kHasPrimitive)]: false, [Symbol(asyncId)]: 248, [Symbol(triggerId)]: 246 } }, parser: HTTPParser { '0': null, '1': [Function: parserOnHeaders], '2': [Function: parserOnHeadersComplete], '3': [Function: parserOnBody], '4': [Function: parserOnMessageComplete], '5': [Function: bound onParserExecute], '6': [Function: bound onParserTimeout], _headers: [], _url: '', socket: [Circular *1], incoming: [Circular *2], outgoing: null, maxHeaderPairs: 2000, _consumed: true, onIncoming: [Function: bound parserOnIncoming], joinDuplicateHeaders: null, [Symbol(resource_symbol)]: [HTTPServerAsyncResource] }, on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], setEncoding: [Function: socketSetEncoding], _paused: false, _httpMessage: ServerResponse { _events: [Object: null prototype], _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, strictContentLength: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, _closed: false, socket: [Circular *1], _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], req: [Circular *2], _sent100: false, _expect_continue: false, _maxRequestsPerSocket: 0, [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(kBytesWritten)]: 0, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype], [Symbol(errored)]: null, [Symbol(kHighWaterMark)]: 16384, [Symbol(kRejectNonStandardBodyWrites)]: false, [Symbol(kUniqueHeaders)]: null }, [Symbol(async_id_symbol)]: 250, [Symbol(kHandle)]: TCP { reading: true, onconnection: null, _consumed: true, [Symbol(owner_symbol)]: [Circular *1] }, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(shapeMode)]: true, [Symbol(kCapture)]: false, [Symbol(kSetNoDelay)]: true, [Symbol(kSetKeepAlive)]: false, [Symbol(kSetKeepAliveInitialDelay)]: 0, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0 }, _consuming: false, _dumped: false, [Symbol(shapeMode)]: true, [Symbol(kCapture)]: false, [Symbol(kHeaders)]: { host: 'localhost:8888', connection: 'keep-alive', 'content-length': '45', 'sec-ch-ua-platform': '"Windows"', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36', accept: 'application/json, text/plain, */*', 'sec-ch-ua': '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"', 'content-type': 'application/json', 'x-custom-header': 'foobar', 'sec-ch-ua-mobile': '?0', origin: 'http://localhost:5173', 'sec-fetch-site': 'same-site', 'sec-fetch-mode': 'cors', 'sec-fetch-dest': 'empty', referer: 'http://localhost:5173/', 'accept-encoding': 'gzip, deflate, br, zstd', 'accept-language': 'zh-CN,zh;q=0.9' }, [Symbol(kHeadersCount)]: 34, [Symbol(kTrailers)]: null, [Symbol(kTrailersCount)]: 0 }

原生node.js接收前端数据

复制代码

//接收数据 let body = ''; // 每次接收到一部分数据,就累加到 body req.on('data', chunk => { body += chunk.toString(); }); // 数据接收完毕后,在这里处理完整的 body req.on('end', () => { //解析JSON格式 try { const data = JSON.parse(body); console.log('接收到的数据:', data); res.end('ok'); } catch (err) { console.error('解析失败:', err); res.statusCode = 400; res.end('Invalid JSON'); } });

req.on

复制代码

在 Node.js 的 HTTP 服务器处理中,`req.on` 用于监听 HTTP 请求对象 (`IncomingMessage`) 的事件。`req` 是一个继承了 `EventEmitter` 类的对象,可以通过 `.on()` 方法监听各种请求相关的事件。 以下是常见的 `req.on` 使用场景和详细解释: --- ### 1. **接收请求体数据(POST/PUT 等)** 当客户端通过 POST 或 PUT 方法发送数据时,数据会被分成多个 **chunk(数据块)** 传输。你需要监听 `'data'` 和 `'end'` 事件来完整接收数据。 ```javascript const http = require('http'); const server = http.createServer((req, res) => { let body = []; // 监听 'data' 事件:每次接收到数据块时触发 req.on('data', (chunk) => { body.push(chunk); // 将数据块存入数组 }); // 监听 'end' 事件:所有数据接收完成后触发 req.on('end', () => { body = Buffer.concat(body).toString(); // 合并所有数据块 console.log('Received body:', body); res.end('Data received'); }); }); server.listen(3000); ``` - **为什么需要这样处理?** HTTP 请求体可能很大,Node.js 以流(Stream)的形式逐步传输数据,避免内存溢出。 --- ### 2. **处理请求错误** 监听 `'error'` 事件可以捕获请求过程中发生的错误(如客户端提前断开连接)。 ```javascript req.on('error', (err) => { console.error('Request error:', err); // 可以在此处关闭连接或清理资源 }); ``` --- ### 3. **其他事件** - **`'close'`**: 当底层连接关闭时触发。 - **`'aborted'`**: 当请求被客户端中止时触发。 --- ### 4. **注意事项** - **必须监听 `'data'` 才会触发 `'end'`** 如果你不监听 `'data'` 事件,流会处于 **暂停模式**,`'end'` 事件永远不会触发。 - **流(Stream)的工作模式** - **流动模式(Flowing Mode)**: 通过 `.on('data')` 自动接收数据。 - **暂停模式(Paused Mode)**: 需要手动调用 `.read()` 读取数据。 - **框架的封装** 在 Express 或 Koa 等框架中,通常使用中间件(如 `body-parser`)自动处理请求体数据,无需手动监听 `'data'` 和 `'end'`。 --- ### 5. **完整示例** ```javascript const http = require('http'); const server = http.createServer((req, res) => { let data = ''; req.on('data', (chunk) => { data += chunk; // 拼接数据块(字符串形式) }); req.on('end', () => { try { const jsonData = JSON.parse(data); // 解析 JSON 数据 res.end('Data processed'); } catch (err) { res.statusCode = 400; res.end('Invalid JSON'); } }); req.on('error', (err) => { console.error('Request error:', err); res.statusCode = 500; res.end('Internal Server Error'); }); }); server.listen(3000, () => { console.log('Server running on port 3000'); }); ``` --- ### 6. **Express 中的对比** 在 Express 中,使用 `express.json()` 中间件后,可以直接通过 `req.body` 获取解析后的数据,无需手动监听事件: ```javascript const express = require('express'); const app = express(); app.use(express.json()); // 自动处理 JSON 请求体 app.post('/', (req, res) => { console.log(req.body); // 直接访问解析后的数据 res.send('Data received'); }); app.listen(3000); ``` --- ### 总结 - **`req.on`** 用于监听 HTTP 请求对象的事件,适用于原始 Node.js 环境。 - 主要事件:`data`(接收数据块)、`end`(数据接收完成)、`error`(处理错误)。 - 在框架中(如 Express),通常有更简洁的封装,无需直接操作这些事件。

相关推荐
汇能感知4 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun4 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao5 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾5 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT5 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
ST.J6 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin6 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全
小憩-7 小时前
【机器学习】吴恩达机器学习笔记
人工智能·笔记·机器学习
UQI-LIUWJ7 小时前
unsloth笔记:运行&微调 gemma
人工智能·笔记·深度学习
googleccsdn7 小时前
ESNP LAB 笔记:配置MPLS(Part4)
网络·笔记·网络协议