Nodejs 接收 POST 请求时,绑定 end 事件为何不是执行一次

发布于 1周前 作者 gougou168 来自 nodejs/Nestjs

Nodejs 接收 POST 请求时,绑定 end 事件为何不是执行一次

代码 login.html <html> <head> <meta http-equiv=“content-type” content=“text/html; charset=UTF-8” /> </head> <body> <form action=“http://localhost:8080/” method=“post”> 用户名:<input type=“text” name=“name”> </br> 密码:<input type=“password” name=“pwd”></br> <input type=“submit” value=“登录”> </form> </body> </html>

post.js

var http = require(‘http’);

http.createServer(function (req, res) { var postData = ‘’;

// 设置接收数据编码格式为 UTF-8
req.setEncoding('utf-8');

// 接收数据块并将其赋值给 postData req.addListener(“data”, function(postDataChunk) { postData += postDataChunk; });

req.addListener(“end”, function() { // 数据接收完毕,执行回调函数

console.log('1')

});

res.end();

}).listen(8080, ‘localhost’);

出现的问题是: req.addListener(“end”, function() { // 数据接收完毕,执行回调函数

    console.log('1')
});

这个不是只执行一次 而是在运行程序的时候 被执行了两次 不知道为什么 希望高手帮助一下新手


5 回复

在 Node.js 中处理 HTTP POST 请求时,req 对象是一个可读流(Readable Stream),它会根据客户端发送的数据分块传输。因此,req 对象上的 end 事件会在所有数据块传输完成后触发一次,而不是多次。

但是,如果你遇到 end 事件被多次触发的情况,这可能是由于以下几种原因导致的:

  1. 多次请求:确保你的服务器没有因为某些配置或逻辑错误而重复处理同一个请求。
  2. 客户端行为:客户端可能发送了多个请求到服务器。

让我们通过一个简单的示例来演示如何正确地处理 POST 请求,并确保 end 事件只被触发一次:

示例代码

HTML 表单 (login.html)

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<form action="http://localhost:8080/" method="post">
用户名:<input type="text" name="name"> <br>
密码:<input type="password" name="pwd"><br>
<input type="submit" value="登录">
</form>
</body>
</html>

Node.js 服务器 (post.js)

const http = require('http');

http.createServer((req, res) => {
    let postData = '';

    // 设置接收数据编码格式为 UTF-8
    req.setEncoding('utf-8');

    // 接收数据块并将其赋值给 postData
    req.on('data', (postDataChunk) => {
        postData += postDataChunk;
    });

    req.on('end', () => {
        // 数据接收完毕,执行回调函数
        console.log('Received data:', postData);

        // 返回响应
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end('登录成功');
    });

    // 注意:这里的 res.end() 应该放在适当的位置,而不是立即调用
    // res.end();  // 这行应该被注释掉,因为我们希望在数据接收完毕后才结束响应
}).listen(8080, 'localhost');

console.log('Server running at http://localhost:8080/');

解释

  1. req.on('data', ...): 当接收到数据块时,将这些数据块拼接到 postData 变量中。
  2. req.on('end', ...): 当所有数据块都接收完毕后,触发 end 事件,此时你可以处理完整的请求数据。
  3. res.end(): 在处理完数据后,调用 res.end() 结束响应。

通过这种方式,end 事件只会被触发一次,即在所有数据块都接收完毕后。这样可以确保数据处理逻辑不会被多次执行。


代码格式化出错啊楼主…

楼主可以把req.url打印出来。我猜测应该是favicon导致的把?

谢谢朋友,是由于favicon引起的,已经测试过了 谢谢

当你在Node.js中使用req.addListener("end", ...)监听POST请求时,如果发现end事件被触发了多次,这通常是由于请求被多次发送到服务器。例如,可能是客户端表单提交了两次,或者在网络请求中有重复的数据流。

为了解决这个问题,可以确保每次只处理一个POST请求。你可以通过引入会话管理或者状态标志来避免这种情况。此外,确保在处理完一个请求后才开始处理下一个请求。

以下是改进后的代码示例:

var http = require('http');

http.createServer(function (req, res) {
    var postData = '';

    req.setEncoding('utf-8');

    req.on("data", function(postDataChunk) {
        postData += postDataChunk;
    });

    req.on("end", function() {
        // 数据接收完毕,执行回调函数
        console.log('1');
        console.log(postData);

        // 清空postData以便处理下一个请求
        postData = '';
        
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('OK\n');
    });

}).listen(8080, 'localhost');

在这个示例中,每次接收到end事件时,我们打印出postData并将其清空,以准备处理下一个请求。这样可以确保每个请求的数据不会干扰其他请求。

如果你仍然遇到问题,检查客户端表单是否意外地发送了多次请求,或网络配置是否有问题。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!