在fs.readFile()的callback函数中使用Email.send时发生meteor“光纤”错误

当我尝试在Email.send的callback中使用Email.send时,我得到Error('Can\'t wait without a fiber') 。 如果我直接打电话给Email.send我不会得到这个错误。

这是错误:

 (STDERR) /Users/james/.meteor/packages/meteor-tool/.1.1.8.tvnipv++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:155 throw new Error('Can\'t wait without a fiber'); ^ => Exited with code: 8 (STDERR) Error: Can't wait without a fiber at Function.wait (/Users/james/.meteor/packages/meteor-tool/.1.1.8.tvnipv++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:155:9) at Object.Future.wait (/Users/james/.meteor/packages/meteor-tool/.1.1.8.tvnipv++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:397:10) at smtpSend (packages/email/email.js:86:1) at Object.Email.send (packages/email/email.js:176:1) at email.js:49:17 at fs.js:272:14 at Object.oncomplete (fs.js:108:15) 

这是我的JavaScript。 请注意,我使用了一个虚拟的MAIL_URL来保护无辜者。

 if (Meteor.isClient) { var to = 'you@example.com' var from = 'me@example.com' var title = 'Message' var message = "emails/message.html" Meteor.call( 'sendEmail' , to , from , title , message , callback ) function callback(error, data) { console.log(error, data) } } if (Meteor.isServer) { Meteor.startup(function () { // REPLACE WITH YOUR OWN MAIL_URL FOR OUTGOING MESSAGES process.env.MAIL_URL = 'smtp://me%40example.com:PASSWORD@smtp.example.com:25'; // HACK TO FIND public/ DIRECTORY IN Meteor 1.2.0.1 var _public = "../../../../../public/" var fs = Npm.require('fs'); Meteor.methods({ sendEmail: function (to, from, subject, file) { var self = this var data = file check([to, from, subject, file], [String]); fs.readFile(_public + file, 'utf8', function (err, data) { if (err) { console.log('Error: ' + err); return; } // Let other method calls from the same client start, // running without waiting for the email sending to // complete. self.unblock(); Email.send({ // ERROR OCCURS HERE to: to, from: from, subject: subject, html: data }); }); } }); }); } 

如果我绕过对fs.readFile的调用,通过添加注释如下所示一切正常:

  // fs.readFile(_public + file, 'utf8', function (err, data) { // if (err) { // console.log('Error: ' + err); // return; // } // Let other method calls from the same client start, // running without waiting for the email sending to // complete. self.unblock(); Email.send({ // ERROR HERE to: to, from: from, subject: subject, html: data }); // }); 

你能帮我理解为什么在最初的情况下需要fiber ,我应该如何提供fiber

meteor方法调用总是在光纤内部运行,这为Node事件循环callback风格提供了一个同步的API。

您可以使用Meteor.wrapAsync将asynchronousfs.readFile调用转换为同步调用:

 var fsReadFileSync = Meteor.wrapAsync(fs.readFile, fs); var data = fsReadFileSync(_public + file, 'utf8'); Email.send(...); 

编辑:

Meteor.wrapAsync使用fs.readFileSync封装asynchronous读取和使用fs.readFileSync什么fs.readFileSync ? 包装的asynchronous读取导致更好的性能?

fs.readFileSync将阻止Node事件循环,因此仅用于诸如命令行实用程序之类的内容。

相反,被包装的fs.readFile看起来像阻塞事件循环来同步执行I / O任务,但是仍然使用非阻塞callback机制。

在一个web服务器应用程序中,你真的不希望你的Node进程被I / O任务阻塞,因为这意味着它可能不能尽快地回应客户请求。