如何使Meteor方法同步?

17

我需要一种让 Meteor 调用同步的方法,以便在运行调用时,代码等待结果完成,以便可以继续客户端上的下一行代码。

例如:

clientFunction = function(){

    Meteor.call('serverFunction', function(err,result){})//<--so when this gets a result and    
                                                    //is stored in a session variable
    var doSomeThing = Session.get('whatever') <-- so that your able to use it here
}

我尝试使用 while 循环来防止在返回值之前发生任何事情,但似乎它在客户端函数之后运行,导致其失败。

任何帮助将不胜感激。


为什么不在回调函数中设置/doSomething它呢? - Firo
我会这样做,但是直到客户端代码运行完成后才会设置该值。 - cronicryo
如果您能更详细地解释一下您想要做什么,那可能会有所帮助。根据您当前的代码,您可以将var doSomething的代码移动到回调函数中。基于您目前的情况,没有理由不起作用。阻塞客户端并不是一个好主意,异步回调就是为了防止这种情况发生的。 - Firo
我有7个集合,每个集合都有指定的分离类来处理各个类别。例如:this.add = function (name, number,status,type, brand, agency){ return Projects.insert({ name:name, number:number, status:status, visibility:true, dateCreated: new Date(), dateModified:new Date(), type: type, brand:brand, agency:agency, spots:[], archive:false }); };但是我不能在函数中放置一个调用来返回值。 - cronicryo
3个回答

12

这是一个非常常见的问题,以各种形式被问到。大多数人不会意识到自己正在进行异步调用。然而,解决方案总是相同的:将服务器上的方法代码包装成fiber或使用future。

我认为最好的做法是使用当前可用的Meteor._wrapAsync函数,如下所述: Meteor: Calling an asynchronous function inside a Meteor.method and returning the result

还有一些其他选项在这里描述: https://gist.github.com/possibilities/3443021


更新:该方法现在称为Meteor.wrapAsync


我实际上尝试过这个,但控制台一直输出“Object has no method _wrapAsync” Object Meaning Meteor。 - cronicryo
你可能正在调用客户端吗?我刚刚确认,在meteor的最近两个版本中,此功能仍然存在:在服务器端:console.log(Meteor._wrapAsync)会打印[Function],即它是存在的。 - Christian Fritz

2

将想要在方法完成后运行的代码放入方法回调中。这是任何异步JavaScript的标准。

clientFunction = function(){
  Meteor.call('serverFunction', function(err, result){
    if (err) {
      alert(err);
    } else {
      Session.set('whatever', result.whatever);
    }
  });
};

方法调用返回后,设置了会话变量的值。现在您可以使用Meteor的反应性来使用该变量:

Template.hello.helpers({
  myWhatever: function () {
    var whatever = Session.get('whatever');

    if (whatever) return whatever;

    return 'Loading whatever...';
  }
});

2
Meteor.call 是异步的,这意味着定义上来说,在 Meteor.call 后面的代码不会等待其完成。这就是任何异步调用的工作方式。这就是为什么异步调用有回调函数,允许您在结果返回后执行代码。如果您需要等待返回值,则需要将“下一行代码”放入回调函数中。 - alanning
我完全理解异步调用,我的意思是你的解决方案只适用于模板,因为它依赖于反应式属性,而不是一个通用的解决方案。_wrapAsync 看起来是一个更好的方法... - ncubica
1
将依赖于远程调用结果的代码放在回调函数中是一种通用解决方案,也是编写JavaScript异步代码的标准方式。Meteor在服务器端利用Fibers来避免这个问题。这个问题的上下文是在客户端运行的代码(我们可以通过原始问题包括使用Session的方式来判断这一点)。wrapAsync(它使用Fibers)是服务器端代码的好解决方案。在客户端,你必须使用如我上面所示的回调方法。 - alanning
这个答案不是同步客户端方法调用,而是异步的。 - Lawrence Weru
@LarryW.,在客户端上不存在同步的Meteor方法调用。Meteor 文档也指出了这一点,因为客户端没有Fibers。因此,实现用户想要的将Meteor方法调用的结果放入Session变量的方法是使用提供的回调机制。 - alanning
显示剩余2条评论

1
我按照this教程操作,做了以下的事情:
这是一个Meteor服务器端的方法。
productIdResult:function(searchstring)
{
   {
      var skimlinks_query = Async.wrap(skimlinks.query);
      var title_val="title:\"electric bicycle\"  AND merchantCategory:*bikes*";                     
      var result = skimlinks_query({
                        searchFor: searchstring,
                        start:start,
                        rows:rows,
                        fq: "country:US"
                    });
      return result;
}

我将其翻译为中文:"

然后我像这样从客户端调用它

"。
Meteor.call('productIdResult',
            searchstring,
            function(error,resul)
            {
                arr[0]=resul.skimlinksProductAPI.products[0].title;
                $( "#op1").autocomplete({source:arr});

            }
);

请注意这不是同步的,但您可以在回调函数中获得返回值。


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