Node.js心得筆記

npm init 可用npm 來調試node項目

瀏覽器中的頂級對象時window

<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),通常有更簡潔的封裝,無需直接操作這些事件。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81332.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81332.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81332.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡01-網站數據傳輸過程

局域網&#xff1a; 覆蓋范圍小&#xff0c;自己花錢買設備&#xff0c;寬帶固定&#xff0c;自己維護&#xff0c;&#xff0c;一般長度不超過100米&#xff0c;&#xff0c;&#xff0c;帶寬也比較固定&#xff0c;&#xff0c;&#xff0c;10M&#xff0c;&#xff0c;&…

Mysql常用函數解析

字符串函數 CONCAT(str1, str2, …) 將多個字符串連接成一個字符串。 SELECT CONCAT(Hello, , World); -- 輸出: Hello World??SUBSTRING(str, start, length) 截取字符串的子串&#xff08;起始位置從1開始&#xff09;。 SELECT SUBSTRING(MySQL, 3, 2); -- 輸出: SQ…

SpringMVC 前后端數據交互 中文亂碼

ajax 前臺傳入數據&#xff0c;但是后臺接收到的數據中文亂碼 首先我們分析一下原因&#xff1a;我們調用接口的時候傳入的中文&#xff0c;是沒有亂碼的 此時我們看一下Java后臺接口對應的編碼&#xff1a; 默認情況&#xff1a;Servlet容器&#xff08;如Tomcat&#xff09;默…

loads、dumps、jsonpath使用場景

在處理JSON數據時&#xff0c;loads、dumps 和 jsonpath 是三個非常有用的工具或概念。它們各自在不同的場景下發揮作用&#xff0c;讓我們一一來看&#xff1a; 1. loads loads 函數是 Python 中 json 模塊的一部分&#xff0c;用于將 JSON 格式的字符串解析成 Python 的數據…

Java學習手冊:Spring 事務管理

一、事務管理的概念 事務是一組操作的集合&#xff0c;這些操作要么全部成功&#xff0c;要么全部失敗。事務管理的目的是保證數據的一致性和完整性。在數據庫操作中&#xff0c;事務管理尤為重要&#xff0c;例如銀行轉賬、訂單支付等場景都需要事務管理來確保數據的正確性。…

echarts自定義圖表--柱狀圖-橫向

區別于縱向表格 xAxis和yAxis對調 要將label全部固定到最右側&#xff1a; 隱藏一個柱形 為每個label設置固定的偏移距離 offset: [300 - 80, 0] 在data中加入label的配置 根據現在的值生成距離右側的偏移 更新方法 chart.setOption({series: [{},{data: data.map(v > ({v…

【CV數據集】Visdrone2019無人機目標檢測數據集(YOLO、VOC、COCO格式)

visdrone2019的Task1是非常通用的目標檢測數據集&#xff0c;也是許多人做目標檢測論文和項目必然會用到的數據集&#xff0c;我將該數據集進行了處理&#xff0c;將其YOLO、VOC和COCO格式都整理好&#xff0c;通過下載我整理好的數據集和相關文件&#xff0c;可以直接在自己的…

常見電源的解釋說明

英文縮寫 BJT&#xff08;bipolar junction transistor&#xff09;雙極型結晶體管FET&#xff08;field-effect transistor&#xff09;場效應管TTL&#xff08;Transistor-Transistor Logic&#xff09;三極管CMOS&#xff08;Complementary Metal Oxide Semiconductor&…

【2025年五一數學建模競賽】A題 解題思路與模型代碼

2025年五一數學建模競賽 A題 問題一&#xff1a;推測支路 1 和支路 2 的車流量 1.1 問題描述 根據提供的主路歷史數據以及已知的支路車流量變化趨勢&#xff08;支路1呈線性增長&#xff0c;支路2先線性增長后線性減少&#xff09;&#xff0c;推測這兩個支路在特定時間段&a…

d202551

目錄 一、175. 組合兩個表 - 力扣&#xff08;LeetCode&#xff09; 二、511. 游戲玩法分析 I - 力扣&#xff08;LeetCode&#xff09; 三、1204. 最后一個能進入巴士的人 - 力扣&#xff08;LeetCode&#xff09; 一、175. 組合兩個表 - 力扣&#xff08;LeetCode&#xf…

RISC-V AIA SPEC學習(四)

第五章 Interrupts for Machine andSupervisor Levels 核心內容?? 1.主要中斷類型與默認優先級:?? 定義了機器級別(M-level)和監管者級別(S-level)的標準中斷類型(如MEI、SEI、MTI等)。默認優先級規則:本地中斷(如軟件/定時器)優先級高于外部中斷,RAS事件(如低/高…

WSGI(Web Server Gateway Interface)服務器

0、什么是 WSGI WSGI &#xff08;Web Server Gateway Interface&#xff09; 是一種Python規范&#xff0c;它定義了 Web 服務器 和 Python Web 應用程序之間的通信接口。 即&#xff0c;能夠讓各種 Web 服務器&#xff08;如 Nginx、Apache 等&#xff09;和 Python Web 框架…

博客打卡-人類基因序列功能問題動態規劃

題目如下&#xff1a; 眾所周知&#xff0c;人類基因可以被認為是由4個核苷酸組成的序列&#xff0c;它們簡單的由四個字母A、C、G和T表示。生物學家一直對識別人類基因和確定其功能感興趣&#xff0c;因為這些可以用于診斷人類疾病和設計新藥物。 生物學家確定新基因序列功能…

基本功能學習

一.enum枚舉使用 E_SENSOR_REQ_NONE 的定義及用途 在傳感器驅動開發或者電源管理模塊中&#xff0c;E_SENSOR_REQ_NONE通常被用來表示一種特殊的狀態或請求模式。這種狀態可能用于指示當前沒有活動的傳感器請求&#xff0c;或者是默認初始化狀態下的一種占位符。 可能的定義…

vitest | 測試框架vitest | 總結筆記

目錄 測試框架 vitest 介紹 測試文件的寫法 文件取名&#xff1a;文件名中要有 test&#xff0c;即 xxx.test.ts 引入庫&#xff1a; test 測試&#xff1a; 測試運行&#xff1a; npx test 文件名 &#xff0c;每次保存后會重新運行。 ★ expect 方法&#xff1a; v…

ESP32開發-作為TCP客戶端發送數據到網絡調試助手

??代碼&#xff08;作為TCP客戶端&#xff09;?? #include <SPI.h> #include <EthernetENC.h> // 使用EthernetENC庫// 網絡配置 byte mac[] {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // MAC地址 IPAddress ip(192, 168, 1, 100); // ESP32的IP IPAddr…

HTML5 WebSocket:實現高效實時通訊

一、引言 在當今的 Web 開發領域,實時通訊功能變得越來越重要。例如在線聊天、實時數據更新等場景都需要客戶端與服務器之間能夠進行高效的雙向數據傳輸。HTML5 引入的 WebSocket 協議為我們提供了一種強大的解決方案,它在單個 TCP 連接上實現了全雙工通訊,極大地改善了傳統…

速通Ollama本地部署DeepSeek-r1

下載 Ollama 前往 Ollama官網 下載客戶端&#xff0c;下載完成后點擊Install安裝即可。 完成后會自動安裝在C:盤的AppData文件夾下&#xff0c;命令行輸入ollama后&#xff0c;顯示下圖中的信息表明安裝成功。 下載模型 在官網界面點擊 DeepSeek-R1 超鏈接 跳轉到DeepSeek安裝…

總結C++中的STL

1.STL 概述 STL 即標準模板庫&#xff0c;是 C 標準程序庫的重要組成部分&#xff0c;包含常用數據結構和算法&#xff0c;體現了泛型化程序設計思想&#xff0c;基于模板實現&#xff0c;提高了代碼的可復用性 2.容器 2.1 序列容器&#xff1a; 1. vector 特性&#xff…

自動駕駛-一位從業兩年的獨特視角

時間簡介 2023.03 作為一名大三學生&#xff0c;加入到某量產車企&#xff0c;從事地圖匹配研發 2023.07 地圖匹配項目交付&#xff0c;參與離線云端建圖研發 2023.10 拿到24屆校招offer 2024.07 正式入職 2025.01 離線云端建圖穩定&#xff0c;開始接觸在線車端融圖研發 自動…