【问题标题】:Nodejs Express - res.send(<a very long string>) freeze when sending result back to clientNodejs Express - res.send(<a very long string>) 将结果发送回客户端时冻结
【发布时间】:2021-04-23 09:54:32
【问题描述】:

我是 JS 和 Node.js 的新手。我昨天才开始学习它,所以我可能没有以正确的方式做事。

我有一个 NodeJS 应用程序,我使用 express 建立了一个服务器。客户端将向该服务器发出获取请求,服务器将执行一些 API 调用/计算,然后当结果准备好时,服务器会将结果发送回客户端。这就是我现在拥有的

app.mjs


app.get('/log', function (req, res) {
  ...
  function callback(data) {
    res.send(data);
  }
  deviceHandler.getLog(filteredDevices, callback);
}
)

还有 deviceHander.mjs


class DeviceHandler {
  ...
  getLog(device, callback) {
    var handler = this.deviceHandlers[device.type]
    handler.getLog(device, callback)
  }
}

其中一个设备是 iPhone,所以这里是 iphoneDeviceHandler.mjs 的 sn-p

IphoneDeviceHandler.prototype.getLog = function(device, callback) {
  get(url, callback);
};

终于来了我的get函数

function get(url, callback, method='GET') {
  var http = new XMLHttpRequest();
  http.open(method, url, true);
  ...
  http.onload = function() {
    if (http.status != 200) {
      callback(`Error ${http.status}: ${http.statusText}`);
    } else { // show the result
      // callback(http.responseText) <--- this freeze
      console.log(Buffer.byteLength(http.responseText, "utf-8")); <-----1323196 bytes so 1.3 MB but sometimes it can be up to 5MB
    }
  };
  http.send();
}


这可行,但我认为我做错了什么,因为我的终端在我拨打一个电话后一直冻结所有内容。以下是问题

  1. 在我向本地主机服务器发出请求后,终端冻结。不确定为什么,但我怀疑这与我的回调函数有关?它是在我添加回调后开始的。
  2. 获取日志操作需要一段时间,这就是我使用同步调用http.open(method, url, false);的原因。那样可以么?我听说同步在 JS 世界中通常是不受欢迎的? (我再次对它超级陌生)或者我应该执行异步操作,但是如何在 app.mjs 中调用 res.send() 之前将响应返回给客户端?
  3. 推荐的返回进度的方法是什么?

【问题讨论】:

    标签: javascript node.js express asynchronous xmlhttprequest


    【解决方案1】:

    您应该设置响应状态,如果需要,您还可以设置 cookie 和标头

    res.status(200).json({数据})

    【讨论】:

    • 您好,欢迎来到 StackOverflow!你能给出一些精确的例子/解释吗?
    • const jwtToken = jwt.sign({ sub: user._id, id: user._id, role: user.role, }, config.SECRET, { expiresIn: 30 }) //30 秒res.cookie('jwt-token', jwtToken, { maxAge: COOKIE_EXPIRES, httpOnly: false, sameSite: true, secure: false }) res.status(201).json({ user: { login: user.login, _id : user._id, 角色: user.role }, 刷新: refToken.token })
    • 上面,我给出了一个在响应cookie中创建和设置授权令牌的代码示例
    • 当然你应该在循环之外调用响应
    【解决方案2】:

    从上面的代码 sn-p 中,我看到了您在 foreach 循环中使用回调的地方。根据我的经验,我能理解的是你应该在整个过程结束时调用回调,

    此外,您在回调中使用 res.send(),而回调是循环的一部分。 (如果您通过一个设备,那么它可以,但对于多个设备,它将运行 res.send() 多次) 如果你运行 res.send() 一次,那么客户端将不会收到未来的 res.send() 因为连接将从两端关闭。

    【讨论】:

    • 欢迎来到 SO!谢谢!这就说得通了。我更新了代码以在 for 循环之外发送一次,但在我向 localhost 的服务器发出一个请求后它仍然冻结。我更新了上面的代码以反映我现在所拥有的
    • 冻结问题可能与其他问题有关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2021-09-25
    • 2021-10-07
    • 2019-07-20
    • 1970-01-01
    相关资源
    最近更新 更多