在节点服务器中使用 res.end() 时出现问题



下面是我的服务器.js文件中的代码片段。运行时,我发送一个带有消息的 URL,res.end() 会导致视图呈现空白页。

当我注释掉 res.end() 命令时,视图显示所有消息,但浏览器等待并等待来自服务器的响应完成的信号。

我知道您可以使用res.end()并将数据放入parens中,由视图传输和呈现。

我期望发生的是,如果没有参数,它只会留下视图,但括号中的空参数表现为空视图。

如何在不删除视图数据的情况下指示响应已完成?

服务器.js

var   http = require('http'),
url = require('url'),
fs = require('fs');
var   messages = ["testing"];
var   clients = [];
http.createServer(function(req,res) {
var url_parts = url.parse(req.url);
console.log(url_parts);
if(url_parts.pathname == '/') {
// file serving
fs.readFile('./index.html', function(err, data) {
// console.log(data);
res.end(data);
});
} else if(url_parts.pathname.substr(0,5) == '/poll'){
//polling code
var count = url_parts.pathname.replace(/[^0-9]*/,'');
console.log(count);
if(messages.length > count){
res.end(JSON.stringify({
count: messages.length,
append: messages.slice(count).join("n")+"n"
}));
} else {
clients.push(res);
}
} else if(url_parts.pathname.substr(0, 5) == '/msg/') {
// message receiving
var msg = unescape(url_parts.pathname.substr(5));
messages.push(msg);
while(clients.length > 0) {
var client = clients.pop();
client.end(JSON.stringify({
count: messages.length,
append: msg+"n"
}));
}
// res.end(); //if left in, this renders an empty page, if removed,
// client keeps waiting....
}
}).listen(8080, 'localhost');
console.log('server running!');

索引.html

<html>
<head>
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script>
var counter = 0;
var poll = function() {
$.getJSON('/poll/'+counter, function(response) {
counter = response.count;
var elem = $('#output');
elem.text(elem.text() + response.append);
//elem.text(counter);
poll();
});
}
poll();
</script>
</head>
<body>
<textarea id="output" style="width: 90%; height: 90%;">
</textarea>
</body>
</html>

我已经查看了文档,但我没有看到任何关于使用带有空参数的 .end() 方法来表示和结束而不传递要呈现的数据的具体内容。我已经用谷歌搜索过这个,但我还没有答案。

do a res.json({success:"true"}) 代替。原因是因为 res.end 本质上认为客户端在流关闭之前被发送了视图。使用 res.json(),您可以发送任何通用数据,而无需隐含视图,也可以关闭客户端和服务器端的流。

在循环内移动res.end()while

while (clients.length > 0) {
var client = clients.pop();
client.end(JSON.stringify({
count : messages.length,
append : msg + "n"
}));
if(!clients.length) {
res.end();
}
}

我对你的问题的理解是:

  1. 您有一个 HTML 页面 (index.html),该页面有一个显示用户提交的所有邮件的textarea。收到并显示一条消息后,它将立即发送下一条消息的请求(/poll/<n>)。
  2. 要接受用户对最新消息的输入,请打开 API (/msg/<message>)。当 HTTP 请求发送到此 API 时,服务器将提取消息,并将此消息返回到步骤 1 中发送/poll/<n>
  3. 但是,由于 HTML 页面 (index.html) 和对/msg/<message>的请求发生在同一个浏览器窗口中,你不能让 node.js 中/msg/<message>的 http 处理程序调用res.end(),因为在这种情况下,浏览器窗口将呈现/msg/<message>请求(空白页)的 HTTP 响应。实际上,无论返回什么数据,您都无法使res返回 200 OK。您也不能使res失败/msg/<message>请求(使用req.destroy()),因为在这种情况下,浏览器窗口将呈现失败/损坏的页面,情况更糟。
  4. 不幸的是,您无法在 node 中res/msg/<message>.js也保持挂起状态。虽然它会更新index.html,但浏览器窗口将继续等待...

问题的根本原因是:index.html/msg/<message>响应之间的浏览器窗口资源冲突 - 只要使用窗口的URL栏发送/msg/<message>请求index.html每当其响应被发送回时,窗口内容(index.html)将被清理。

一种解决方案是:使用 Ajax 发送/msg/<message>。这样,窗口资源就不会发生冲突。下面列出了示例代码:

<body>
<textarea id="output" style="width: 90%; height: 90%;">
</textarea>
<div>
<input type="text" id="msg">
<button type="button" onclick="submitMsg()">Submit</button>
</div>
</body>
window.submitMsg = function() {
var msg = $('#msg').val();
$.getJSON('/msg/' + msg, function(res) {
$('#msg').val('');
console.log('message sent.');
});
}

编辑: 另一个更简单的解决方案是:在一个浏览器窗口中打开index.html,在另一个浏览器中打开/msg/<message>(使用res.end('message received successfully')指示消息接收结果)。

相关内容

最新更新