Meteor [Error: Can't wait without a fiber] after a call to Email.send

Meteor [Error: Can't wait without a fiber] after a call to Email.send

我使用 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没有使用回调函数。

我应该怎么做才能消除错误?

发生这种情况是因为虽然您的 Meteor.startup 函数 运行 位于 Fiber 中(就像几乎所有其他 Meteor 回调一样),但您使用的 setTimeout 却没有!由于 setTimeout 的性质,它将 运行 在顶部范围内,在您定义 and/or 调用函数的纤程之外。

要解决,您可以使用 Meteor.bindEnvironment:

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

然后每次调用 setTimeout 时都这样做,这是一个令人痛苦的事实。
幸好事实并非如此。只需使用 Meteor.setTimeout 而不是原生的:

Meteor.setTimeout(sendMail, eta_ms);

来自文档:

These functions work just like their native JavaScript equivalents. If you call the native function, you'll get an error stating that Meteor code must always run within a Fiber, and advising to use Meteor.bindEnvironment

流星计时器 bindEnvironment then delay the call 如您所愿。