重新启动 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 请求库“只为您处理”的事情。
我正在尝试克服 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 请求库“只为您处理”的事情。