【问题标题】:Why will my subsequent Meteor method calls not wait for the first one to finish when I call Meteor.setTimeout()?当我调用 Meteor.setTimeout() 时,为什么我的后续 Meteor 方法调用不会等待第一个方法完成?
【发布时间】:2015-03-20 02:15:00
【问题描述】:

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

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

多次触发'click button'事件时,终端输出如下:

outside
outside
outside
outside
inside
inside
inside
inside

而不是像我期望的那样在outsideinside 之间交替。我认为关于Meteor.setTimeout() 有一些非常相关的信息,但我在文档中找不到任何表明这种行为的信息。我错过了什么,有没有办法让客户端的 Meteor 方法调用等到前一个调用完成后再开始执行下一个?

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

【问题讨论】:

    标签: javascript meteor


    【解决方案1】:

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

    为了提供更好的测试(以及在方法中使用异步函数的示例),试试这个:

    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 回调的返回值实际上并没有去任何地方,它只是减少了 that 函数(即回调,not 方法)。按照上面的写法,Future 对象 fut 在回调运行后被提供返回值,但在提供该值之前,主方法函数(仍在其原始光纤中运行)被阻止返回.

    结果是除非你unblock这个方法,否则你会得到预期的输出,因为下一个方法调用在前一个方法返回之前不会开始。

    更新

    一般来说,任何带有回调的东西都会在当前 Fiber 关闭后将回调添加到事件循环中,因此超时、HTTP 调用、异步 DB 查询——所有这些都属于这一类。如果要在回调中重新创建方法的环境,则需要使用Meteor.bindEnvironment,否则无法使用任何 Meteor API 功能。 This 是一个旧的,但非常关于这个主题的好视频。

    【讨论】:

    • 谢谢!我试过了,该方法现在按我预期的那样工作。把这个问题更进一步,我怎么知道什么会在同一根光纤中运行,什么不会?例如,一个集合的更新会在同一个纤程中运行吗?
    猜你喜欢
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2011-11-18
    • 1970-01-01
    相关资源
    最近更新 更多