【问题标题】:Trouble using res.end() in a node server在节点服务器中使用 res.end() 时遇到问题
【发布时间】:2017-04-14 03:35:57
【问题描述】:

所以,下面是我的 server.js 文件中的代码 sn-p。运行时,我发送一个带有消息的 URL, res.end() 导致视图呈现一个空白页面。

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

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

我期望发生的是,没有 args,它只会留下视图,但括号中的空 args 表现为一个空视图。

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

server.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!');

index.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() 方法来表示和结束而不传递要呈现的数据的具体内容。我已经用谷歌搜索了这个,但我还没有答案。

【问题讨论】:

  • 你能发布完整的工作代码吗?
  • When I comment out the res.end() command, the view displays all of the messages,你是怎么做到的?您的代码没有显示client.end() 的任何逻辑
  • @abhyudit-jain,server.js 文件的完整工作代码现已发布在上面,提前感谢您的想法
  • @abhyudit-jain 我也添加了 html 文件
  • @shaochuancs 我不明白你的评论,你能改写一下吗?我所知道的是,如果我注释掉 res.end(),则会显示消息,但浏览器会继续期待更多数据。

标签: javascript node.js http server


【解决方案1】:

改为执行 res.json({success:"true"})。原因是 res.end 本质上认为客户端在流关闭之前已发送视图。使用 res.json() 您可以发送任何通用数据,而不需要隐含的视图以及关闭客户端和服务器端的流。

【讨论】:

  • 我收到以下错误:TypeError: res.json is not a function。那是因为 .JSON 是一个快速函数,而不是一个节点函数吗?我在这个应用程序中不需要 Express(至少现在还不需要),只需要 http
【解决方案2】:

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();
    }
}

【讨论】:

  • 我试过这个,与我上面的代码相同的问题,例如,当调用 /msg/message 时,我可以确定它已发布,但随后它被删除,大概是由空的 .end() 命令。谢谢你的帮助。还有其他想法吗?
【解决方案3】:

我对你的问题的理解是:

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

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

一种解决方案是:使用 Ajax 发送/msg/&lt;message&gt;。这样,窗口资源就不会发生冲突。示例代码如下:

<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/&lt;message&gt;(使用res.end('message received successfully')表示消息接收结果)。

【讨论】:

  • 我回家时必须看看这个。似乎有道理。我知道当我打开多个浏览器,然后从一个浏览器发送消息时,其他浏览器会正确更新,这很好,但是我发送的浏览器会被清除。
  • @CaptainChaos 你的问题解决了吗?如果是,也许您可​​以“接受”其中一个答案?
  • 我忙于其他事情。我还没有找到答案,但还没有尝试所有推荐的方法。我会在一周左右的时间内回到这个问题上。感谢您的耐心和提醒
猜你喜欢
  • 1970-01-01
  • 2020-02-18
  • 2016-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多