如何使 Meteor 方法同步?

Posted

技术标签:

【中文标题】如何使 Meteor 方法同步?【英文标题】:How to make Meteor methods synchronous? 【发布时间】:2014-05-05 07:27:50 【问题描述】:

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

例如:

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 循环来防止在返回值之前发生任何事情,但它似乎在 clientFunction 之后运行,因此将其推向了死亡

任何帮助将不胜感激

【问题讨论】:

你为什么不在回调中设置/做一些事情呢? 我会这样做,直到客户端代码运行完成后才会设置值 如果您多解释一下您正在尝试做什么,这可能会有所帮助。使用您当前的代码,您可以将您的 var doSomething 代码移动到回调中。根据您所拥有的,没有理由不这样做。阻止客户端不是一个好主意,这就是异步回调旨在防止的。 我有 7 个带有指定分离类的集合来处理单个级别的类,例如 this.add = function (name, number,status,type, brand, agency) return Projects.插入(名称:名称,编号:编号,状态:状态,可见性:true,dateCreated:新日期(),dateModified:新日期(),类型:类型,品牌:品牌,机构:机构,点:[],存档:假); ;但我不能在函数中调用来重新运行值 【参考方案1】:

我按照this 教程做了类似下面的操作

这是一个流星服务器端方法

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);

            
);

注意不是同步的,而是在回调中获取返回值

【讨论】:

【参考方案2】:

这是一个非常常见的问题,被以各种形式和形式提出。大多数人在进行异步调用时都没有意识到。然而,解决方案始终是相同的:将服务器上的方法代码包装到纤程中或使用未来。

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

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


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

【讨论】:

我确实尝试过这个并且控制台一直吐出“对象没有方法_wrapAsync”对象含义流星 您可能在拜访客户吗?我刚刚确认,在上两个版本的流星中,这个功能仍然存在:在服务器上:console.log(Meteor._wrapAsync) 打印[Function],即它存在。【参考方案3】:

将方法完成后要运行的代码放入方法回调中。这是任何异步 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...';
  
);

【讨论】:

如果您正在等待Meteor.call 的值在下一行代码中执行一些操作,则此方法不起作用... Meteor.call 是异步的,这意味着根据定义,Meteor.call 之后的下一行代码不会等待其完成。这就是任何异步调用的工作方式。这就是异步调用有回调的原因,允许您仅在结果返回后执行代码。如果您需要等待返回值,则需要将“您的下一行代码”放入回调中。 为了完整起见,Meteor 提供了一种替代方法,可以将依赖于返回值的代码放在回调中。相反,让依赖于返回值的代码使用反应变量(如Session),然后在回调中将返回值存储在反应变量中。 我完全理解异步调用,我说你的解决方案只适用于模板,因为反应性属性而不是通用解决方案,_wrapAsync 看起来是一个更好的方法...... 将依赖于远程调用结果的代码放入回调中是一种通用解决方案,并且是编写 javascript 异步代码的标准方式。 Meteor 在服务器端使用Fibers 来避免这种情况。这个问题的上下文是在客户端上运行的代码(我们可以这样说,因为原始问题包括使用Session,这是仅限客户端的)。 wrapAsync(使用 Fibers)是服务器端代码的一个很好的解决方案。在客户端,你必须使用我上面展示的回调方法。

以上是关于如何使 Meteor 方法同步?的主要内容,如果未能解决你的问题,请参考以下文章

Meteor 同步方法调用

初识Angular-Meteor(Angular-Meteor使实时全栈更简单)

Meteor 的 DDP 在同步非常大的集合方面的效率如何?

使输入上的 disabled 属性与 Meteor 助手反应的最佳方法是啥?

使用 Meteor 方法从 MongoDB 下载大量文档

如何使 Meteor React 内联 svg 元素单击页面链接而不刷新整个页面