Meteor.methods返回未定义 [英] Meteor.methods returns undefined

查看:44
本文介绍了Meteor.methods返回未定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用流星0.6.4.

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

每执行一次它就会返回未定义

 Meteor.call('random', 10);
 

有什么想法可以克服这个问题吗?

解决方案

这是完全正常的行为:Meteor中的服务器方法调用是 Meteor.call("myMethod", arguments..., function(error, result){ if(error){ console.log(error.reason); return; } // do something with result });

服务器方法结果发送回客户端后,匿名回调函数将在客户端上被调用.

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

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

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

要定义此类方法存根,只需在客户端代码上定义相同的服务器方法名称. 如果方法声明是在共享代码中定义的(同时提供给客户端和服务器),则可以通过检查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复制的本地数据库子集的修改),因此此行为有点奇怪. /p>

I'm using meteor 0.6.4.

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

It returns undefined whenever I execute

Meteor.call('random', 10);

Any ideas how I can get past this?

解决方案

This is a perfectly normal behavior: server method calls in Meteor are documented to be asynchronous :

On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method.

It means that when you ask for a Meteor.call method to execute remotely on the server, the local method call is non blocking and returns undefined immediately. When the method has been called on the server it will send the result asynchronously to the client, so you should retrieve it using the callback pattern :

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

The anonymous callback function will be called on the client as soon as the server method result is sent back to the client.

There is another subtle feature in Meteor invalidating what I just said : latency compensation and methods stubs. In case the server method call can be SIMULATED properly in the client and thus executed right away without a round-trip to the server, you can define what is called a method stub (or simulation).

A common use case for this behavior is inserting immediately in the local (client side replication subset) database some user content just posted (a comment under a blog article for example) : all the necessary data and logic is available and it makes sense to simulate server side insertion. What happens next is that the user sees the webpage updated as soon as he submitted his content even if the server hasn't acknowledged these changes yet. (this is an example how latency compensation is implemented in Meteor).

Of course the server has final words on what gets ultimately inserted in the database, this means that when the server side twin method is executed, its actions will take precedence and replace what was inserted in the local database.

To define such method stub, you just have to define the same server method name on client code. If the method declaration is defined in shared code (shipped both to client and server), you can test if the method call is actually a simulation by checking the isSimulation property :

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

UPDATE 26/11/2014 : @steph643 commented on how the last part of my previous answer was actually wrong, here is a correction.

Note that on the server method calls can always be invoked using the synchronous syntax because server environment provides adequate blocking mechanism (fibers).

On the client however, if you return something from a method stub, it can be executed synchronously only if you're inside another stub and you can retrieve the result in a synchronous way, ie

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

This behavior is a bit weird considering that Mongo collection operations (insert/update/delete) are implemented as Meteor methods and their client versions are implementing valid stubs (modification of minimongo replicated local database subset) that can be executed synchronously.

这篇关于Meteor.methods返回未定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆