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 事件每次都触发了,求解


3 回复

在 Node.js 中处理 HTTP POST 请求时,req 对象是一个可读流(Readable Stream),它会发出多个 data 事件,每个事件包含一部分请求体的数据。如果 data 事件没有被触发,可能是因为请求体为空或者请求的编码方式不正确。

让我们详细分析并提供一个修正后的示例代码:

问题分析

  1. 请求体为空:确保客户端发送了数据。
  2. 请求编码错误:确保服务器正确地设置了字符编码。
  3. 使用正确的监听器方法:从 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.');

代码解释

  1. 导入模块:导入 httpurl 模块。
  2. 路由处理函数:定义一个简单的路由处理函数 route
  3. onRequest 函数
    • 初始化 postData 为一个数组,用于存储每次 data 事件触发时接收到的数据片段。
    • 监听 data 事件,并将每次接收到的数据片段添加到 postData 数组中。
    • 监听 end 事件,在请求结束时将 postData 数组中的所有数据片段拼接成完整的字符串,并调用路由处理函数。
  4. 启动服务器:创建 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 和实际的数据内容。

回到顶部