Meteor中的mongo find()出现了UnhandledPromiseRejectionWarning,最大调用堆栈大小超过限制。

5

在我的Meteor应用中进行mongodb查找时出现了奇怪的错误。控制台显示的错误为:

(node:20388) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2):
RangeError: Maximum call stack size exceeded

我搜索过一些类似的例子,但我的情况不同,与数据大小无关 -- 这是一个非常简单的查询,无论查询内容如何都会发生。

在客户端,我这样做:

Meteor.call( 'Things.search', searchString,(error,result) => {
      if(error){
        console.log(error);
      } else {
        console.log("Got result");
        ...

当它从服务器端返回并没有错误时,它会立即返回,结果是未定义的而不是光标。服务器端会执行以下操作:

Meteor.methods({
  'Things.search'( searchString ) {
    check(searchString, String);
    process.on('unhandledRejection', r => console.log(r));
    try {
      let searchOptions = "$i";
      let result = Things.find({
        $or:[
          {typeOfThing:{ $regex: searchString, $options: searchOptions }},
          {name:{ $regex: searchString, $options: searchOptions }}]
        });
      return result;
    } catch (exception) {
      console.log( exception );
      throw new Meteor.Error('500', exception);
    }
  },
});

在另一个论坛上的建议中,我添加了process.on()以揭示更多关于未处理的promise的底层信息。添加后,控制台还显示了以下额外信息:

RangeError: Maximum call stack size exceeded
I20180202-20:38:14.522(-5)?     at Object.keys.forEach.key (packages/ejson/ejson.js:594:27)
I20180202-20:38:14.522(-5)?     at Array.forEach (<anonymous>)
I20180202-20:38:14.525(-5)?     at Object.EJSON.clone.v [as clone] (packages/ejson/ejson.js:594:18)
I20180202-20:38:14.527(-5)?     at Object.keys.forEach.key (packages/ejson/ejson.js:595:22)
I20180202-20:38:14.528(-5)?     at Array.forEach (<anonymous>)
I20180202-20:38:14.530(-5)?     at Object.EJSON.clone.v [as clone] (packages/ejson/ejson.js:594:18)
I20180202-20:38:14.549(-5)?     at Object.keys.forEach.key (packages/ejson/ejson.js:595:22)
I20180202-20:38:14.551(-5)?     at Array.forEach (<anonymous>)
I20180202-20:38:14.553(-5)?     at Object.EJSON.clone.v [as clone] (packages/ejson/ejson.js:594:18)
I20180202-20:38:14.554(-5)?     at Object.keys.forEach.key (packages/ejson/ejson.js:595:22)

使用chrome服务端调试器与Meteor 1.6一起使用后,我确认在ejson.js中存在一个无限循环。

看起来像是不属于我的错误 -- 我怀疑find()不应该陷入无限循环。有人对此有什么想法吗?


2
返回find().fetch(),因为方法不是响应式的,只应该返回数据。对于响应式数据观察,您应该使用我们的发布功能。 - Jankapunkt
好知道,谢谢!这是我第一次尝试传回一个游标而不使用发布。我错过了某个地方,你不应该尝试这样做。虽然我觉得它应该更优雅地失败。 - RealHandy
我知道我已经在GitHub上开了一个问题,关于错误信息完全令人困惑的事实。 - Jankapunkt
我不确定是否设置 process.on('unhandledRejection', r => console.log(r)); 会导致问题 - 基本上每次调用该方法时都会添加错误处理程序,并且在方法完成后没有将其删除。 - Mikkel
那没有造成任何损害。我只是在出现问题后添加它,以便我可以获得更多的错误信息(正如上面显示的那样)。 - RealHandy
1个回答

6
我找到了一半的答案和一个解决方法,但现在看起来更可能是一个错误。如果我只在服务器端执行fetch(),而不是尝试返回游标,它就可以正常工作!所以,这个方法可行:
  let result = Things.find({
    $or:[
      {typeOfThing:{ $regex: searchString, $options: searchOptions }},
      {name:{ $regex: searchString, $options: searchOptions }}]
    }).fetch(); // <--- This fetch makes it all work fine!

没有使用.fetch(),这里的结果会立即返回为无效(如调试器所示),因为所有内容都会在无限循环中崩溃。

所以,我通过返回fetch()的结果来解决这个问题。没有返回fetch()的结果是我的错误,但也是一个Meteor问题,不返回结果会导致无法报告有用的错误信息并进入无限循环。


这是正确的。你不能将光标发送到客户端,而需要使用方法返回已获取的文档。这是由于Meteor在内部处理集合和光标的方式所致。 - Jankapunkt
我正在使用事件从方法中访问数据。然后,我想在返回的数据上调用一个集合助手方法。但是,我不能在获取的文档上执行此操作,因为它不是游标,对吗?有没有解决这个问题的方法?谢谢! - user2402616
@user2402616 不确定 - 你可能需要开一个单独的问题来询问。 - RealHandy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接