重新启动 Node 函数时超出调用堆栈大小

Call stack size exceeded on re-starting Node function

我正在尝试克服 Call stack size exceeded 错误,但没有成功,

目标是重新运行 GET 请求,只要我在type 字段中得到music

//tech: node.js + mongoose
//import components
const https = require('https');
const options = new URL('https://www.boredapi.com/api/activity');


//obtain data using GET
https.get(options, (response) => {
  //console.log('statusCode:', response.statusCode);
  //console.log('headers:', response.headers);

  response.on('data', (data) => {
        //process.stdout.write(data);
        apiResult = JSON.parse(data);
        apiResultType = apiResult.type;
        returnDataOutside(data);
  });
 })

.on('error', (error) => {
  console.error(error);
 });


function returnDataOutside(data){
  apiResultType;

  if (apiResultType == 'music') {
    console.log(apiResult);
  } else {
    returnDataOutside(data);
    console.log(apiResult); //Maximum call stack size exceeded
  };
};

您的函数 returnDataOutside() 正在递归调用自身。如果它第一次没有得到 'music'apiResultType ,那么它只会越来越深入地调用自己,直到堆栈溢出而没有机会获得 music 类型,因为你只是一遍又一遍地用相同的数据调用它。

当您没有 music 类型时,您似乎想重新运行 GET 请求,但您的代码并没有这样做——它只是一遍又一遍地调用您的响应函数。因此,相反,您需要将发出 GET 请求的代码放入函数中,并在 apiResultType 不是您想要的时调用实际发出新 GET 请求的新函数。

此外,您不应该编写这样的代码,因为它会永远攻击某些服务器。您应该有最大尝试次数或计时器回退或两者都有。

而且,您不能假设 response.on('data', ...) 包含 JSON 的完美格式。如果数据不是很小,那么数据可能以任意大小的块到达。它需要多个 data 事件才能获得您的整个有效载荷。而且,这可能适用于快速网络,但不适用于慢速网络或通过某些代理,但不适用于其他代理。相反,您必须从连接在一起的整个响应(发生的所有 data 事件)中累积数据,然后处理 end 事件的最终结果。

同时,您可以编写简单的代码 https.get() 来为您收集所有结果(doc here 中有一个这样的示例),使用更高级别会容易得多为一堆有用的东西提供支持的库。

在这方面我最喜欢使用的库是 got(), but there's a list of alternatives here,您可以找到自己喜欢的那个。这些库不仅会在您编写任何额外代码时为您累积整个请求,而且它们是基于承诺的,这使得异步编码更容易,它们还会自动为您检查状态代码结果,遵循重定向等...... - 许多您希望 http 请求库“只为您处理”的事情。