当我调用Meteor.setTimeout()时,为什么我的后续Meteor方法调用不等待第一个方法完成? [英] Why will my subsequent Meteor method calls not wait for the first one to finish when I call Meteor.setTimeout()?

查看:133
本文介绍了当我调用Meteor.setTimeout()时,为什么我的后续Meteor方法调用不等待第一个方法完成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对流星,纤维和未来都相当新,我试图了解Meteor方法的工作原理。据我所知,来自客户端的每个方法调用都会等待前一个方法完成。这种信念主要基于 this.unblock()函数的文档。流星文档。但是,当我尝试使用 Meteor.setTimeout()调用设置一个简单示例时,这似乎不是一个正确的假设。

I am fairly new to Meteor, fibers and futures and I am trying to understand how Meteor methods work. It is my understanding that each method call from a client would wait for a previous one to finish. This belief is mostly based on the documentation of the this.unblock() function in the Meteor docs. However, when I try setting up a simple example with a Meteor.setTimeout() call this does not seem to be a correct assumption.

methodCall.js:

methodCall.js:

if (Meteor.isClient) {
  Template.hello.events({
    'click button': function () {
      Meteor.call('test', function(error, result){
      });
    }
  });
}

if (Meteor.isServer) {
  Meteor.methods({
    test: function(){
      console.log("outside");
      Meteor.setTimeout(function(){
          console.log("inside");
          return 'done';
      }, 2000);
    }
  });
}

触发'点击按钮'事件多次终端输出如下:

When triggering the 'click button' event several times the terminal output is as follows:

outside
outside
outside
outside
inside
inside
inside
inside

并且不会像我期望的那样在之外的之间的之间交替。我认为在 Meteor.setTimeout()上有一个非常相关的信息我错过了,但我在文档中找不到任何指示此行为的内容。我缺少什么,有没有办法让客户端的Meteor方法调用等到上一次调用完成后才开始执行下一个?

and not alternating between outside and inside as I would expect. I think there is a very relevant bit of information on Meteor.setTimeout() I am missing, but I could not find anything in the documentation indicating this behaviour. What am I missing and is there a way of making the Meteor method invocations from a client wait until a previous invocation is finished before starting the execution of the next?

我找到了这个问题在SO看起来很有希望,但问题更侧重于阻止从客户端调用该方法的可能性。同样,接受的答案并不完全令人满意,因为它侧重于使后续调用跳过Meteor方法的某些代码块而不是等待第一次调用完成。这就是我想的答案,但我真的很想理解为什么方法调用首先没有被阻止,因为我觉得Meteor文档表明了这一点。

I found this question on SO which seemed promising, but the question is more focused on blocking the possibility to call the method from the client side. Likewise, the accepted answer is not completely satisfying as it focuses on making subsequent calls skip certain code blocks of the Meteor method instead of waiting for the first invocation to finish. This very well be the answer I guess, but I really want to understand why the method call is not blocked in the first place as I feel the Meteor documentation indicates.

推荐答案

答案是setTimeout回调是在运行该方法的光纤之外执行的。这意味着该方法实际上在调用setTimeout回调之前完成执行(返回 undefined ),并且您得到了您观察到的行为。

The answer is that the setTimeout callback is executed outside the fiber in which the method is running. What that means is that the method actually finishes execution (returning undefined) before the setTimeout callback is ever invoked, and you get the behavior you observed.

要提供更好的测试(以及在方法中使用异步函数的示例),请尝试以下方法:

To provide a better test (and for an example of using asynchronous functions in methods), try this:

if (Meteor.isServer) {
  var Future = Npm.require('fibers/future');

  Meteor.methods({
    test: function(){
      var fut = new Future();
      console.log("outside");
      Meteor.setTimeout(function(){
          console.log("inside");
          fut.return('done');
          return 'done';
      }, 2000);
      return fut.wait();
    }
  });
}

你的setTimeout回调的返回值实际上并没有去任何地方,它只是缩减 功能(即回调,方法)。上面写的方式,Future对象 fut ,一旦回调运行就会提供返回值,但主方法函数(仍在其原始光纤中运行)在这个值被提供之前,它被阻止返回。

The return value from your setTimeout callback doesn't actually go anywhere, it just curtails that function (i.e. the callback, not the method). The way it's written above, the Future object, fut, is supplied with the return value once the callback runs, but the main method function (which is still running in its original fiber) is prevented from returning until that value has been supplied.

结果是除非你取消阻止这个方法,您将获得预期的输出,因为下一个方法调用在前一个方法调用返回之前不会开始。

The upshot is that unless you unblock this method, you will get the expected output as the next method invocation won't start until the previous one has returned.

更新

通常,任何带回调的东西都会在当前光纤关闭后将回调添加到事件循环中,因此超时,HTTP调用,异步数据库查询 - 所有这些都归入此类别。如果要在回调中重新创建方法的环境,则需要使用 Meteor.bindEnvironment 否则您无法使用任何Meteor API功能。 这个是旧的,但非常关于这个主题的好视频。

In general, anything with a callback will have the callback added to the event loop after the current Fiber is closed, so timeouts, HTTP calls, asynchronous DB queries - all of these fall into this category. If you want to recreate the environment of the method within the callback, you need to use Meteor.bindEnvironment otherwise you can't use any Meteor API functionality. This is an old, but very good video on the subject.

这篇关于当我调用Meteor.setTimeout()时,为什么我的后续Meteor方法调用不等待第一个方法完成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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