Meteor.methods返回undefined

时间:2013-07-04 00:19:59

标签: meteor

我正在使用meteor 0.6.4。

Meteor.methods({
  random: function(top){
    var random = Math.floor((Math.random()*(top+1)));
    return random;
  }
});

每次执行

时都会返回undefined
Meteor.call('random', 10);

我有什么想法可以解决这个问题?

1 个答案:

答案 0 :(得分:60)

这是完全正常的行为:Meteor中的服务器方法调用documented是异步的:

  

在客户端上,如果你没有传递一个回调并且你不在一个存根中,那么调用将返回undefined,你将无法获得该方法的返回值。

这意味着当您要求在服务器上远程执行Meteor.call方法时,本地方法调用是非阻塞的,并立即返回undefined。 在服务器上调用该方法后,它会将结果异步发送到客户端,因此您应该使用回调模式检索它:

Meteor.call("myMethod", arguments..., function(error, result){
  if(error){
    console.log(error.reason);
    return;
  }
  // do something with result
});

一旦将服务器方法结果发送回客户端,就会在客户端上调用匿名回调函数。

Meteor中还有另一个微妙的功能使我刚才所说的无效:延迟补偿和方法存根。 如果服务器方法调用可以在客户端中正确模拟并因此立即执行而无需往返服务器,则可以定义所谓的方法存根(或模拟)。

此行为的一个常见用例是在本地(客户端复制子集)数据库中立即插入一些刚刚发布的用户内容(例如博客文章下的评论):所有必要的数据和逻辑都可用,它使得模拟服务器端插入的意义。 接下来发生的事情是,即使服务器尚未确认这些更改,用户也会在提交内容后立即更新网页。 (这是一个如何在Meteor中实现延迟补偿的例子。)

当然,服务器对最终插入数据库的内容有最后的说法,这意味着当执行服务器端双方法时,其操作将优先并替换本地数据库中插入的内容。

要定义此类方法存根,您只需在客户端代码上定义相同的服务器方法名称。 如果方法声明是在共享代码中定义的(同时发送到客户端和服务器),则可以通过检查isSimulation属性来测试方法调用是否实际上是模拟:

Meteor.methods({
    myMethod: function(arguments...){
        if(this.isSimulation){
            // called from the client
        }
    }
});

更新26/11/2014:@ steph643评论了我之前答案的最后部分是如何实际错误的,这是一个更正。

请注意,在服务器上,方法调用始终可以使用同步语法调用,因为服务器环境提供了足够的阻塞机制(光纤)。

但是在客户端上,如果从方法存根中返回一些内容,只有当你在另一个存根中时才可以同步执行,并且可以以同步方式检索结果,即

Meteor.methods({
  intermediateMethod: function(){
    return " WORLD";
  },
  method: function(){
    var result = "HELLO";
    result += intermediateResult;
    var intermediateResult = Meteor.call("intermediateMethod");
    return result;
  }
});

考虑到Mongo集合操作(​​插入/更新/删除)是作为Meteor方法实现的,并且它们的客户端版本正在实现可以同步执行的有效存根(minimongo复制的本地数据库子集的修改),这种行为有点奇怪。 / p>