调用Email.send后,Meteor [错误:不能没有光纤等待]

Jam*_*ton 6 timeout callback fiber meteor

我使用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)
      }
    }
  })
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以Meteor.wrapAsync用来制作光纤.但是wrapAsync期望有一个回调来调用,并且Email.send不使用回调.

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

Kyl*_*yll 10

发生这种情况是因为当你的Meteor.startup函数在光纤内运行时(就像几乎所有其他的Meteor回调一样),setTimeout你使用的不是!由于setTimeout它的性质,它将运行在顶部示波器上,在您定义和/或调用该功能的光纤之外.

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

setTimeout(Meteor.bindEnvironment(sendMail), eta_ms);
Run Code Online (Sandbox Code Playgroud)

然后每次拨打电话都这样做setTimeout,这是一个非常难的事实.
好事实际上并非如此.只需使用Meteor.setTimeout而不是原生的:

Meteor.setTimeout(sendMail, eta_ms);
Run Code Online (Sandbox Code Playgroud)

来自文档:

这些函数就像它们的原生JavaScript等价物一样工作.如果您调用本机函数,您将收到一条错误消息,指出Meteor代码必须始终在光纤内运行,并建议使用Meteor.bindEnvironment

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