6

我使用 Meteor 创建了一个非常简单的服务器,用于在超时后发送电子邮件。当我使用超时时,消息成功发送但抛出错误:[Error: Can't wait without a fiber].

这是我的代码:

if (Meteor.isServer) {
  Meteor.startup(function () {
    // <DUMMY VALUES: PLEASE CHANGE>
    process.env.MAIL_URL = 'smtp://me%40example.com:PASSWORD@smtp.example.com:25';
    var to = 'you@example.com'
    var from = 'me@example.com'
    // </DUMMY>
    // 
    var subject = 'Message'
    var message = "Hello Meteor"

    var eta_ms = 10000
    var timeout = setTimeout(sendMail, eta_ms);
    console.log(eta_ms)

    function sendMail() {
      console.log("Sending...")
      try {
        Email.send({
          to: to,
          from: from,
          subject: subject,
          text: message
        })
      } catch (error) {
        console.log("Email.send error:", error)
      }
    }
  })
}

我知道我可以Meteor.wrapAsync用来制造纤维。但是wrapAsync希望有一个回调来调用,并且Email.send不使用回调。

我应该怎么做才能摆脱错误?

4

1 回答 1

10

发生这种情况是因为当您的Meteor.startup函数在 Fiber 中运行时(就像几乎所有其他 Meteor 回调一样),setTimeout您使用的不是!由于它的性质,setTimeout它将在您定义和/或调用函数的光纤之外的顶级范围内运行。

要解决,你可以使用类似的东西Meteor.bindEnvironment

setTimeout(Meteor.bindEnvironment(sendMail), eta_ms);

然后对每个调用都这样做setTimeout,这是一个痛苦的事实。
好在这实际上不是真的。简单地使用Meteor.setTimeout而不是原生的:

Meteor.setTimeout(sendMail, eta_ms);

从文档:

这些函数就像它们的原生 JavaScript 等价物一样工作。如果你调用原生函数,你会得到一个错误,指出 Meteor 代码必须始终在 Fiber 中运行,并建议使用Meteor.bindEnvironment

流星计时器bindEnvironment然后根据需要延迟通话

于 2015-09-23T21:57:24.550 回答