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

问题描述 投票:0回答:4

首先我经常使用 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 编写我的代码并且我没有创建任何名为“async_hooks”的文件。

而且我不会一次运行超过 10 个异步函数,我经常使用 await,所以它不应该堆积,但 javascript 似乎不会减少 asyncId 并很快达到数量限制。

我尝试使用 less async await 但这并没有解决问题,但错误消息稍后出现。如果我使用非常少的 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();

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

javascript typescript asynchronous promise async-await
4个回答
14
投票

当我的设置大小达到 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 的内存,因此如果由于内存限制而崩溃,请相应地增加堆限制。


1
投票

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

class Set {
  hash = {}

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

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

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


0
投票

解决方法(和

Set
一样快)和Unique

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);


0
投票
RangeError: Value undefined out of range for undefined options property undefined

上面的错误是当一个Set达到元素的最大限制时引起的。 请参阅参考资料:Node.js Map 中的最大条目数?

如果仍然遇到问题,您可以尝试

large-set
,一个允许您存储和处理大量元素的包,而不必担心 Set by partitions into 中的 16.777.216 (2^24) 限制当它达到限制时更小的集合,使其能够存储和访问比内置集合更多的元素。

但是如果你不想使用任何包,你可以尝试这个小的解决方法:

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'
}
© www.soinside.com 2019 - 2024. All rights reserved.