4

我正在关注课程stream-adventure。其中一项任务是创建一个 http 服务器,它将所有请求转换为大写并在响应中返回。

现在我设法让它工作并且任务通过了。但是,控制台给了我一个 TimeoutOverflowWarning。

(node:15710) TimeoutOverflowWarning: 4294967296000 does not fit into a 32-bit signed integer.
Timer duration was truncated to 2147483647.
(node:15710) TimeoutOverflowWarning: 4294967296000 does not fit into a 32-bit signed integer.
Timer duration was truncated to 2147483647.

我想知道这是内存泄漏还是由我的代码引起的,还是其他原因。因为在错误消息中提到了 32 位,所以我想知道这是否与我使用 2016 年的 Macbook Pro 以 64 位运行有关。(节点 v10.17.0)

编码:

'use-strict'
const through = require('through2')
const http = require('http')
const port = process.argv[2]

const uppercaser = through(function (buffer, _, next) {
  this.push(buffer.toString().toUpperCase())
  next()
});

const server = http.createServer(function (req, res) {
  if (req.method === 'POST') {
    res.writeHead(200,  { 'Content-Type': 'text/plain' })
    req.pipe(uppercaser).pipe(res)
  } else {
    res.writeHead(404)
    res.end()
  }
});

server.listen(port)

谷歌搜索给出了这个问题的各种原因(示例 1示例 2),并且似乎大多数解决方案在使用的库中都是固定的。

4

3 回答 3

5

当我发现这种类型的错误是在我使用setInterval函数时。

这是因为超时的上限是 2147483647,这是 32 位 int 的最大限制。

如果你愿意,你可以制作自己的setInterval包装

function setDaysTimeout(callback,days) {
    // 86400 seconds in a day
    let msInDay = 86400*1000; 

    let dayCount = 0;
    let timer = setInterval(function() {
        dayCount++;  // a day has passed

        if (dayCount === days) {
           clearInterval(timer);
           callback.apply(this, []);
        }
    }, msInDay);
}

并像这样使用它:

setDaysTimeout(function() {
     console.log('Four days gone');
}, 4); // fire after 4 days
于 2020-05-25T12:54:38.517 回答
5

这是与setTimeout\setInterval函数相关的问题。如您所见,它们的限制为 32 位。所以这node是警告你:

> setTimeout(console.log, +Infinity)

> (node:19903) TimeoutOverflowWarning: Infinity does not fit into a 32-bit signed integer.
Timeout duration was set to 1.

由于您的代码没有任何这些,因此库中的某些代码似乎存在问题。

我建议使用 flag 运行node--trace-warnings 查找警告来源:

--跟踪警告

打印进程警告(包括弃用)的堆栈跟踪。

于 2020-05-25T13:14:08.490 回答
0

超时上限为 2147483647,即 32 位 int 的最大限制。为了避免这种情况,您可以等待最大时间,然后等待任何剩余时间。

const timeout = async (callback, time, callbackArguments) => {
  if (!callback || typeof callback !== 'function') throw new Error('Invalid Callback')
  let args = ((callbackArguments && typeof callbackArguments === 'object' && 
    callbackArguments.length > 0) ? callbackArguments : [])
  let max = 2147483647
  if (time > max) {
    let t = Math.floor(time / max)
    let r = time%max
    for (let i = 0; i < t; i++) await (() => new Promise(res => setTimeout(() => res(), max)))();
    if (r) {
        return setTimeout(() => callback(...args), r)
    } else {
        return callback(...args)
    }
  } else {
    return setTimeout(() => callback(...args), time)
  }
}

像这样使用

let a = 2
let b = 5
let c = (a, b) => console.log(!a && !b ? 0 : !a && b ? b : a && !b ? a : a + b)
let now = new Date().getTime()
let later = now + 2147483647*5
timeout(c, later-now, [a,b])
于 2021-05-10T16:47:13.700 回答