Nodejs新手,res.on('data')只能得到一次数据的问题

Nodejs新手,res.on(‘data’)只能得到一次数据的问题

function start(route, handle) { http.createServer(function(request, response) { var postData = “test”; var pathname = url.parse(request.url).pathname;

    request.addListener("end", function(test) {
        route(handle, pathname, response, postData);
    });

    request.addListener("data", function(chunk) {
        postData += chunk;
        console.log("Recived post data chunk '" + chunk + "'.");
    });
}).listen(8888);

}

如上的代码, 当把request的监听放到函数start中的时候data事件只会触发一次? 求教啊 新手,遇到这个问题很是纠结. 换on触发也没用.


6 回复

Node.js 新手,res.on('data') 只能得到一次数据的问题

背景

在处理 HTTP 请求时,特别是 POST 请求时,你可能会遇到 request.on('data', callback) 只能接收到一次数据的情况。这通常是因为请求的数据可能还没有完全到达,而你的代码已经结束了对数据的监听。

示例代码

让我们来看一个简单的示例,展示如何正确地处理 POST 数据:

const http = require('http');
const url = require('url');

function start(route, handle) {
    http.createServer((request, response) => {
        let postData = '';
        
        // 监听 'data' 事件来接收数据块
        request.on('data', (chunk) => {
            postData += chunk;
            console.log(`Received POST data chunk '${chunk.toString()}'`);
        });

        // 监听 'end' 事件来处理所有数据
        request.on('end', () => {
            route(handle, url.parse(request.url).pathname, response, postData);
        });

        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.end('Hello World\n');
    }).listen(8888);

    console.log('Server has started.');
}

// 这里可以定义路由处理函数
function route(handle, pathname, response, postData) {
    console.log(`About to route a request for ${pathname}`);
    if (typeof handle[pathname] === 'function') {
        handle[pathname](response, postData);
    } else {
        console.log(`No request handler found for ${pathname}`);
        response.writeHead(404, {'Content-Type': 'text/plain'});
        response.end();
    }
}

// 假设 handle 是一个对象,包含不同的路径对应的处理函数
const handle = {
    '/': (response, postData) => {
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('Home Page\n');
        response.end();
    },
    '/upload': (response, postData) => {
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('Upload Page\n');
        response.end();
    }
};

// 启动服务器
start(route, handle);

解释

  1. request.on('data', callback):

    • 这个事件会在每次接收到数据块时被触发。你可以在回调函数中将这些数据块拼接起来。
  2. request.on('end', callback):

    • 这个事件在所有的数据都已经被接收后触发。你可以在这个事件的回调函数中进行进一步的处理,比如调用路由处理函数。

通过这种方式,你可以确保即使数据分多次发送,你也能完整地接收到所有的数据并进行处理。

总结

确保你在处理 HTTP 请求时正确使用 request.on('data', callback)request.on('end', callback) 来处理数据。这样可以避免只接收到一次数据的问题。


触发一次, 收到什么了?

我想 request 是不是不应该加 data listener。你这一加,server 不就收不到数据了,就没法 route 了。所以,你的data listener 被 server 的 data listener 覆盖了。

数据太小了。所以只有一次,你post个大文件上去看看

你是post请求的吗?

不知道你是怎么测试发出http请求的 如果是利用req = http.request();发出的请求,每一次调用req.write();都会发射data事件。 如果是浏览器的话,发送到你的服务器的数据流是不是只有一个,所以只会触发一次data事件

在Node.js中,request对象是可读流(Readable Stream),当处理HTTP请求时,如果请求体比较大或分块传输(Chunked Transfer Encoding),那么data事件可能会被触发多次。你的问题可能是因为request对象的end事件在所有数据都接收完毕后才会触发,而你在requestend事件里调用了路由处理函数,这导致后续的数据不再处理。

为了确保你能够正确处理所有的数据片段,你需要将request.on('data')request.on('end')的监听器放在合适的位置,并且确保在处理完所有数据后再进行路由处理。

以下是一个修改后的示例代码:

const http = require('http');
const url = require('url');

function start(route, handle) {
    http.createServer((request, response) => {
        let postData = '';
        const pathname = url.parse(request.url).pathname;

        request.on('data', (chunk) => {
            postData += chunk;
            console.log(`Received POST data chunk '${chunk}'.`);
        });

        request.on('end', () => {
            route(handle, pathname, response, postData);
        });
    }).listen(8888);

    console.log('Server has started.');
}

// 假设route是一个已经定义好的路由处理函数

解释:

  1. 初始化postData为空字符串:这是用来存储从request中接收到的所有数据。
  2. 监听data事件:每次接收到数据时,将数据追加到postData中,并打印出接收到的数据片段。
  3. 监听end事件:当所有的数据都接收完毕时,调用路由处理函数route()

通过这种方式,你可以确保即使数据是分块传输的,你也能够完整地接收到所有的数据,并在所有数据都到达后进行处理。

回到顶部