作者:无谓__ | 来源:互联网 | 2022-12-09 13:08
您好我上面的问题有点模糊,所以我会尽量让它更清晰.
我有以下形式的代码:
function main () {
async function recursive () {
var a = "Hello World";
var b = "Goodbye World";
recursive();
}
recursive();
}
我遇到的问题是我的堆内存不足.
假设我上面展示的是我的程序行为如何,在递归函数中声明a和b,我的问题是在递归函数中调用递归时是否销毁变量,或者它们是否会持续存在直到不再递归为止调用和main函数到达其端点,假设我保持主函数运行足够长时间以使其发生.
我担心他们在堆中活着,因为我的真实程序在这些变量中存储大字符串,我担心这就是我用完堆的原因.
1> Jacob..:
Javascript(但是?)还没有针对递归的尾调用优化,所以肯定你最终会填满你的调用堆栈.堆填充的原因是因为recursive
定义为async
函数而且永远不会等待分配的Promise
对象解析.这将填满你的堆,因为垃圾收集器没有机会收集它们.
简而言之,除非你在函数中分配堆中的东西,否则递归不会耗尽堆.
扩展正在发生的事情:
main
new Promise(() => {
new Promise(() => {
new Promise(() => {
new Promise(() => {
new Promise(() => { //etc.
你说你不是在等待Promise因为你想让事情并行运行.出于某些原因,这是一种危险的方法.应该总是等待Promise,以防它们抛出,当然你想确保你分配可预测的内存使用量.如果这个递归函数意味着你得到了一个不可预测的所需任务,你应该考虑一个任务队列模式:
const tasks = [];
async function recursive() {
// ...
tasks.push(workItem);
// ...
}
async function processTasks() {
while (tasks.length) {
workItem = tasks.unshift();
// Process work item. May provoke calls to `recursive`
// ...do awaits here for the async parts
}
}
async function processWork(maxParallelism) {
const workers = [];
for (let i = 0; i
最后,如果需要说,async
函数不允许你进行并行处理; 它们只是提供了一种更方便地编写Promise并对异步事件执行顺序和/或并行等待的方法.除非你使用像web worker这样的东西,否则Javascript仍然是单线程执行引擎.因此,使用异步函数尝试并行化同步任务将不会为您做任何事情.