node.js - query - socket io tutorial
¿Cómo puedo generar datos antes de finalizar la respuesta? (4)
Si cambia el tipo de contenido a texto / sin formato, por ejemplo:
// Write Headers
response.writeHead(200, {''Content-Type'': ''text/plain''});
entonces firefox mostrará el contenido de inmediato. Chrome parece funcionar como búfer (si escribe un montón más de contenido, Chrome lo mostrará de inmediato).
Aquí está mi fragmento lo probé en Chrome 11 y Firefox 4:
var http = require(''http'');
http.createServer(function(request, response){
// Write Headers
response.writeHead(200);
// Write Hello World!
response.write("Hello World!");
// End Response after 5 seconds
setTimeout(function(){
response.end();
}, 5000);
}).listen(8000);
Como puede ver, he agotado el tiempo de response.end()
para poder probar si response.write
se emite antes de la response.end
. En mi experiencia, sin embargo, no lo es.
¿Hay alguna forma de generar los datos antes de finalizar la respuesta, algo así como enviar los datos en paquetes?
De hecho, hay una manera de hacerlo sin configurar Content-Type: text/plain
y seguir usando text/html
como Content-Type
, pero debe indicarle al navegador que espere fragmentos de datos.
Esto se puede hacer fácilmente así:
var http = require(''http'');
http.createServer(function(request, response) {
response.setHeader(''Connection'', ''Transfer-Encoding'');
response.setHeader(''Content-Type'', ''text/html; charset=utf-8'');
response.setHeader(''Transfer-Encoding'', ''chunked'');
response.write(''hello'');
setTimeout(function() {
response.write('' world!'');
response.end();
}, 10000);
}).listen(8888);
Sin embargo, debe tener en cuenta que, hasta que se llame a response.end()
la solicitud todavía se está llevando a cabo y bloqueando otras solicitudes al servidor de su nodojs.
Usted puede probar esto abriendo llamando a esta página (localhost: 8888) en dos pestañas diferentes. Uno de ellos esperará 10 segundos, y el otro solo obtendrá el comienzo de la respuesta una vez que finalice la primera respuesta (lo que significa que esperará 10 segundos para el comienzo de la respuesta y otros 10 segundos hasta el final de la respuesta, usando este código).
Probablemente también pueda superar este obstáculo ejecutando un par de procesos nodejs y equilibrando la carga entre ellos, pero luego esto se vuelve mucho más complicado y es un hilo que debería tomarse en otro lugar ... :)
Estos son los puntos principales que debe tener en cuenta:
- especificar un juego de caracteres
- cada "fragmento" será enviado por el navegador (al menos, lo que noté en Chrome) a través de una nueva línea (
<br>
si el juego de caracteres estext/html
)
Al igual que:
res.setHeader(''Content-Type'', ''text/html; charset=utf-8'');
res.write(''a<br>'');
setTimeout(function() {
res.write(''b<br>'');
setTimeout(function() {
res.write(''c'');
res.end();
}, 2000);
}, 2000);
Si desea generar texto plano fragmentado en Chrome , al igual que lo que Firefox está haciendo de manera predeterminada, debe usar el ''X-Content-Type-Options'': ''nosniff''
. Consulte ¿Qué es "X-Content-Type-Options = nosniff"?
var http = require(''http'');
http.createServer(function (req, res) {
res.writeHead(200, {
''Content-Type'': ''text/plain; charset=utf-8'',
''Transfer-Encoding'': ''chunked'',
''X-Content-Type-Options'': ''nosniff''});
res.write(''Beginning/n'');
var count = 10;
var io = setInterval(function() {
res.write(''Doing '' + count.toString() + ''/n'');
count--;
if (count === 0) {
res.end(''Finished/n'');
clearInterval(io);
}
}, 1000);
}).listen(8888);
No necesita esta opción si su salida es text/html
.
Solución encontrada a partir de este defecto de Chrome: codificación de transferencia fragmentada no compatible con texto / normal