Метеор [Ошибка: Не могу ждать без волокна] после вызова 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:[email protected]:25';
    var to = '[email protected]'
    var from = '[email protected]'
    // </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 не использует обратный вызов.

Что мне делать, чтобы избавиться от ошибки?


person James Newton    schedule 23.09.2015    source источник


Ответы (1)


Это происходит потому, что в то время как ваша функция Meteor.startup выполняется внутри волокна (как и почти все другие обратные вызовы Meteor), используемая вами функция setTimeout этого не делает! Из-за природы setTimeout он будет работать в верхней области, за пределами волокна, в котором вы определили и/или вызвали функцию.

Чтобы решить, вы можете использовать что-то вроде Meteor.bindEnvironment:

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

И затем делайте это для каждого отдельного вызова setTimeout, что является болезненно жестким фактом.
Хорошо, что на самом деле это не так. Просто используйте Meteor.setTimeout вместо родного:

Meteor.setTimeout(sendMail, eta_ms);

Из документов:

Эти функции работают так же, как и их нативные эквиваленты в JavaScript. Если вы вызовете нативную функцию, вы получите сообщение об ошибке, в котором говорится, что код Meteor всегда должен выполняться внутри волокна, и рекомендуется использовать Meteor.bindEnvironment

Таймеры Meteor просто bindEnvironment, а затем задерживают вызов по вашему желанию.

person Kyll    schedule 23.09.2015