Nodejs POST 请求 addListener('data',function(postDataChunk){}); 不触发
Nodejs POST 请求 addListener(‘data’,function(postDataChunk){}); 不触发
function onRequest(req,res){
var postData = “”;
var pathname = url.parse(req.url).pathname;
console.log(‘Request ’ + pathname + ’ received.’);
req.setEncoding(‘utf8’);
req.addListener(“data”,function(postDataChunk){
console.log(“进入 data”);
postData += postDataChunk;
console.log(“Received POST data chunk '” + postData +"’.");
});
req.addListener(“end”,function(){
console.log(“进入 end”);
route(handle,pathname,res,postData);
});
}
POST 提交进入都不会触发 data
事件,end
事件每次都触发了,求解
在 Node.js 中处理 HTTP POST 请求时,req
对象是一个可读流(Readable Stream),它会发出多个 data
事件,每个事件包含一部分请求体的数据。如果 data
事件没有被触发,可能是因为请求体为空或者请求的编码方式不正确。
让我们详细分析并提供一个修正后的示例代码:
问题分析
- 请求体为空:确保客户端发送了数据。
- 请求编码错误:确保服务器正确地设置了字符编码。
- 使用正确的监听器方法:从 Node.js v14.9.0 开始,
req.on
方法更推荐用于监听事件。
解决方案
以下是修正后的代码示例:
const http = require('http');
const url = require('url');
// 假设有一个路由处理函数
function route(handle, pathname, res, postData) {
console.log(`About to route a request for ${pathname}`);
if (typeof handle[pathname] === 'function') {
handle[pathname](res, postData);
} else {
console.error(`No request handler found for ${pathname}`);
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.write('404 Not Found');
res.end();
}
}
function onRequest(req, res) {
const postData = [];
const pathname = url.parse(req.url).pathname;
console.log('Request ' + pathname + ' received.');
req.setEncoding('utf8');
req.on('data', function (postDataChunk) {
console.log("进入 data");
postData.push(postDataChunk);
console.log("Received POST data chunk '" + postDataChunk + "'.");
});
req.on('end', function () {
console.log("进入 end");
const postDataString = postData.join('');
route(handle, pathname, res, postDataString);
});
}
const handle = {};
handle['/'] = function (res, postData) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('Hello World!');
res.end();
};
const server = http.createServer(onRequest);
server.listen(8000);
console.log('Server has started.');
代码解释
- 导入模块:导入
http
和url
模块。 - 路由处理函数:定义一个简单的路由处理函数
route
。 - onRequest 函数:
- 初始化
postData
为一个数组,用于存储每次data
事件触发时接收到的数据片段。 - 监听
data
事件,并将每次接收到的数据片段添加到postData
数组中。 - 监听
end
事件,在请求结束时将postData
数组中的所有数据片段拼接成完整的字符串,并调用路由处理函数。
- 初始化
- 启动服务器:创建 HTTP 服务器并监听端口 8000。
通过这种方式,可以确保在接收到完整的 POST 请求体后,正确触发 end
事件并处理请求数据。
找到问题了-.-,提交的表单里面没有给name
根据你的描述,data
事件没有被触发,但 end
事件每次都会触发。这种情况通常发生在请求体非常小或根本没有数据的情况下。data
事件是在接收到请求体数据时触发的,如果请求体很小,可能很快就会触发 end
事件而不会触发 data
事件。
你可以通过检查请求头中的 Content-Length
来确认是否有数据发送。此外,确保你的客户端确实发送了数据。
以下是一个改进的版本,增加了对 req.on('aborted', ...)
的处理,并且使用了更现代的语法:
const http = require('http');
const url = require('url');
function onRequest(req, res) {
let postData = "";
console.log('Request received for ' + url.parse(req.url).pathname);
req.setEncoding('utf8');
req.on('data', function (postDataChunk) {
console.log("进入 data");
postData += postDataChunk;
console.log("Received POST data chunk '" + postData + "'.");
});
req.on('end', function () {
console.log("进入 end");
// 处理路由逻辑
handleRoute(handle, url.parse(req.url).pathname, res, postData);
});
req.on('aborted', function () {
console.log("请求被取消");
});
}
// 示例服务器启动代码
const server = http.createServer(onRequest);
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
请确保你的客户端在发送 POST 请求时包含了实际的数据。例如,使用 curl
或 Postman 发送请求时,确保设置了 Content-Length
和实际的数据内容。