32

我正在使用流星 0.6.4。

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

每当我执行时它都会返回 undefined

Meteor.call('random', 10);

有什么想法我可以通过这个吗?

4

1 回答 1

63

这是一个完全正常的行为:Meteor 中的服务器方法调用被记录为异步:

在客户端,如果你不传递回调并且你不在存根中,调用将返回 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
        }
    }
});

2014 年 11 月 26 日更新:@steph643 评论了我之前回答的最后一部分实际上是错误的,这是一个更正。

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

然而,在客户端,如果您从方法存根返回某些内容,则只有当您在另一个存根中并且您可以以同步方式检索结果时,它才能同步执行,即

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

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

于 2013-07-04T01:13:17.070 回答