【问题标题】:Maximum call stack size exceeded with 2 Collection.find2 Collection.find 超出了最大调用堆栈大小
【发布时间】:2017-11-12 13:24:34
【问题描述】:

我正在使用 Angular2 和 Meteor。由于我在客户端添加了该代码,因此我的 Chrome 控制台中有一个异常(超出了最大调用堆栈大小):

var userChannelsId = UserChannels.find({idUser: Meteor.userId()});
this.channels = Channels.find({_id: {$in: userChannelsId}});

据我发现,当存在无限循环时会发生此异常。我确定错误来自这一行(我调试了我的代码,直到我确定为止)。 问题是否出在第二次开始时第一次搜索没有完成?

所有功能:

getChannelList(): void {
    console.log('ok');
    var userChannelsId = UserChannels.find({idUser: Meteor.userId()});
    this.channels = Channels.find({_id: {$in: userChannelsId}});
    console.log('ko');

    this.channels.subscribe(channel => {
        this.selectChannel(channel[0]);
    });
} 

编辑:

作为@MichaelSolati,我试图只获取 userChannel 的 IdChannel,但我仍然有同样的错误......它返回一个 observable 而不是一个数组。也许是问题所在?这就是我所做的:

getChannelList(): void {
    console.log('ok');
    let userId = Meteor.userId();
    var userChannelsId = UserChannels.find({idUser: userId});
    var values = userChannelsId.map((userChannels:Array<UserChannel>) => {
        let result:Array<String> = [];
        if (userChannels) {
            userChannels.forEach((userChan) => {
                result.push(userChan.idChannel);
            });
        }
        return result;
    });
    this.channels = Channels.find({_id: {$in: values}});
    console.log('ko');
    this.channels.subscribe(channel => { this.selectChannel(channel[0]); });
}

【问题讨论】:

  • 使用setTimeout(function() { // your code here },0}) 避免调用堆栈大小超出问题
  • 我必须在函数中添加什么?我所有的 getChannelList 代码,还是只是我的 Collection.find ?
  • 你必须把你的无限代码放在setTimeout回调函数中
  • 问题是异常触发了超时,我的代码没有执行……所以我认为setTimeout只是避免了问题,并没有解决问题:(
  • 最佳实践是不订阅助手。助手被一遍又一遍地调用,而且可能以你意想不到的方式调用,所以那里的任何操作都应该是幂等的。我通常在 onCreated() 函数中处理我的所有订阅。

标签: javascript mongodb angular meteor


【解决方案1】:

好吧,伙计们,

我找到了一个效果很好的解决方案! 如果您有任何改进我的建议的建议,请随时发表评论,我将不胜感激:)

getChannelList(): void {
    let userId = Meteor.userId();
    UserChannels.find({idUser:userId}).subscribe((userChannel:UserChannel[]) =>{
        var channelsId:Array<String> = [];
        userChannel.forEach((userChan)=>{
            channelsId.push(userChan.idChannel);
        });
        this.channels = Channels.find({_id: {$in: channelsId}});
    });
    if(this.channels !== undefined) {
        this.channels.subscribe(channel => {
            this.selectChannel(channel[0]);
        });
    }
}

谢谢大家的回答。

【讨论】:

    【解决方案2】:

    由于使用 MeteorRxJS 进行查询而更新。虽然它可能并不完美,但它应该能让你走上正确的道路。

    private userChannelsSub: Subscription;
    
    getChannelList(): void {
        console.log('ok');
        let userId = Meteor.userId():
        let this.userChannelsSub = UserChannels.find({idUser: userId}).subscribe((userChannels: any[]) => {
            if (Array.isArray(userChannels)) {
                let userChannelsId = userChannels.map((channel: any) => { return channel._id; });
                if (this.channels) { this.channels.unsubscribe(); }
                this.channels = Channels.find({_id: {$in: userChannelsId}}).subscribe((channels: any[]) => {
                    this.selectChannel(channels[0]); 
                });
            }
        });
        console.log('ko');
    } 
    

    【讨论】:

    • 我按照你的建议做了,但不幸的是,异常仍然在这里:(
    • 等等...您正在尝试获取用户所属频道的列表并搜索他们的所有频道,对吗?但是您将Channels find 查询传递给您UserChannels 查询的完整对象的数组,而不是ID 数组。进行UserChannels 查询后尝试此操作...userChannelsId = userChannelsId.map((channel) =&gt; { return channel._id; });
    • 我编辑了我的帖子,向您展示我是如何尝试的。由于查询返回 UserChannel 数组,因此我不得不稍微修改一下您的提议。告诉我我是否做错了什么。 (它仍然无法正常工作:()
    • 你正在使用 MeteorRxJS 让我很震惊....好吧...这会更痛苦...我会更新我的答案。
    • PS 绝对有比我的解决方案更好的方法来做到这一点,但我有点/非常远离 Meteor 世界,我只是从我记得的事情中吐槽(已经过去了 8 个月) )。
    猜你喜欢
    • 2016-09-26
    • 1970-01-01
    • 2017-12-02
    • 2017-07-02
    • 2020-11-19
    • 2013-08-23
    • 2021-09-07
    • 2015-03-15
    • 1970-01-01
    相关资源
    最近更新 更多