2015-09-23 3 views
5

Я создал очень простой сервер, использующий Meteor, чтобы отправить электронное письмо после таймаута. Когда я использую таймаут, сообщение успешно отправляется, но возникает ошибка: [Error: Can't wait without a fiber].Meteor [Ошибка: не могу ждать без волокна] после звонка по электронной почте.send

Вот мой код:

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 не использует обратный вызов.

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

ответ

9

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

Чтобы решить, вы могли бы использовать что-то вроде 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, как вы хотели.