在 fs.readFile() 的回调中使用 Email.send 时出现 Meteor "fiber" 错误
Meteor "fiber" error when using Email.send in callback from fs.readFile()
当我尝试在来自 fs.readFile
的回调中使用 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
,我应该如何提供?
Meteor 方法调用总是 运行 内部纤程,它提供了一个看起来 API 到 Node 事件循环回调样式的同步。
您可以使用 Meteor.wrapAsync
将异步 fs.readFile
调用转换为同步调用:
var fsReadFileSync = Meteor.wrapAsync(fs.readFile, fs);
var data = fsReadFileSync(_public + file, 'utf8');
Email.send(...);
编辑:
What is the difference between wrapping an async read inside
Meteor.wrapAsync
, and using fs.readFileSync
? Does the wrapped async
read lead to better performance?
fs.readFileSync
将阻止节点事件循环,因此仅用于命令行实用程序等。
一个包裹的fs.readFile
相反,它看起来像是在阻塞事件循环以同步执行I/O任务,但在幕后它仍然使用非阻塞回调机制。
在网络服务器应用程序中,您真的不希望您的 Node 进程被 I/O 任务阻塞,因为这意味着它可能无法尽快响应客户端请求。
当我尝试在来自 fs.readFile
的回调中使用 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
,我应该如何提供?
Meteor 方法调用总是 运行 内部纤程,它提供了一个看起来 API 到 Node 事件循环回调样式的同步。
您可以使用 Meteor.wrapAsync
将异步 fs.readFile
调用转换为同步调用:
var fsReadFileSync = Meteor.wrapAsync(fs.readFile, fs);
var data = fsReadFileSync(_public + file, 'utf8');
Email.send(...);
编辑:
What is the difference between wrapping an async read inside
Meteor.wrapAsync
, and usingfs.readFileSync
? Does the wrapped async read lead to better performance?
fs.readFileSync
将阻止节点事件循环,因此仅用于命令行实用程序等。
一个包裹的fs.readFile
相反,它看起来像是在阻塞事件循环以同步执行I/O任务,但在幕后它仍然使用非阻塞回调机制。
在网络服务器应用程序中,您真的不希望您的 Node 进程被 I/O 任务阻塞,因为这意味着它可能无法尽快响应客户端请求。