我的Javascript是否用完了asyncIds?(inspector_async_hook.js中的RangeError)

wydwbb8l  于 2023-04-10  发布在  Java
关注(0)|答案(4)|浏览(86)

首先,我经常使用async和await,我得到了这个错误:

RangeError: Value undefined out of range for undefined options property undefined
    at Set.add (<anonymous>)
    at AsyncHook.init (internal/inspector_async_hook.js:19:25)
    at PromiseWrap.emitInitNative (internal/async_hooks.js:134:43)

我不知道我怎么能解决这个问题,我写我的代码完全在Typescript,我不创建任何文件,名为'异步挂钩'。
我不会一次运行超过10个函数async,我经常使用await,所以它不应该堆叠起来,但javascript似乎没有减少asyncId,并很快达到数量限制。
我尝试使用更少的async await,但这并没有解决问题,但错误msg稍后出现。如果我使用非常少的async await,我可以防止这个错误出现,直到函数成功完成任务。(我使用Electron 7)
Electron似乎有一个非常低的异步池,但它可以通过默认的类型脚本代码复制:

class Test {
    private async testCompare(a,b):Promise<boolean> {
        return a == b;
    }

    public async testRun():Promise<void> {
        for (let index = 0; index < 999999999; index++) {
            for (let index2 = 0; index2 < 999999999; index2++) {
                await this.testCompare(index,index2)
            }
        }
    }

}
new Test().testRun();

这段代码产生了非常多的内存使用,我想我在我的程序中也有同样的问题。我想异步池被填满了,直到它达到了它的极限。

3phpmpom

3phpmpom1#

当我的集合大小达到16777216(2^24)时,我得到了和你一样的Set.add错误。我无法在文档中找到关于此限制的信息,但我假设集合被限制为16777216个唯一值?
用一个简单的for循环很容易测试。
这将抛出完全相同的错误:

let s = new Set();
for (let i = 0; i <= 16777216; i++) s.add(i);

这将成功运行:

let s = new Set();
for (let i = 0; i < 16777216; i++) s.add(i);

请注意,这将消耗大约5GB的内存,因此如果由于内存限制而崩溃,请相应地增加堆限制。

cgfeq70w

cgfeq70w2#

刚刚在使用Set时遇到了这个问题,我使用以下方法作为快速解决方法

class Set {
  hash = {}

  add (v) {
    this.hash[JSON.stringify(v)] = true
  }

  has (v) {
    return this.hash[JSON.stringify(v)] == true
  }
}

这没有限制,仅受系统内存的限制

acruukt9

acruukt93#

一个解决方案(与Set一样快)和唯一

const setA = {};
try {
    for (let i = 0; i < 16777216 + 500; i++) setA[i] = null;
} catch (err) {
    console.log('Died at ', setA.size, ' Because of ');
    console.error(err);
}

console.log('lived even after ', Object.keys(setA).length);
l0oc07j2

l0oc07j24#

RangeError: Value undefined out of range for undefined options property undefined

当Set达到元素的最大限制时会导致上述错误。参见参考:Node.js Map中的最大条目数?
如果仍然遇到这个问题,你可以尝试large-set,一个允许你存储和处理大量元素的包,而不用担心Set中的16.777.216(2^24)限制,当它达到限制时,它会被分割成更小的集合,使它能够存储和访问比内置Set更多的元素。
但是如果你不想使用任何包,你可以尝试这个小的解决方法:

class LargeSet {
    constructor(limit = 16777216) {
        this.limit = limit;
        this.sets = [new Set()];
    }

    has(value) {
        return this.sets.some(set => set.has(value));
    }

    add(value) {
        if (this.sets[this.sets.length - 1].size >= this.limit) {
            this.sets.push(new Set());
        }
        if (this.has(value)) return this;
        this.sets[this.sets.length - 1].add(value);
        return this;
    }

    delete(value) {
        for (const set of this.sets) {
          if (set.delete(value)) return true;
        }
        return false;
    }
    
    clear() {
        this.sets = [new Set()];
    }
}

然后测试代码:

const largeSet = new LargeSet();
for (let i = 0; i <= 16777216; i++) {
    largeSet.add(i); // No errors will be thrown
}

const set = new Set();
for (let i = 0; i <= 16777216; i++) {
    set.add(i); // Throws a 'RangeError: Value undefined out of range for undefined options property undefined'
}

相关问题