node.js - 在 fs.readFile() 的回调中使用 Email.send 时出现 Meteor "fiber"错误

标签 node.js email meteor fs

当我尝试在 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
      });
    // });

您能否帮助我理解为什么在最初的情况下需要光纤,以及我应该如何提供光纤?

最佳答案

Meteor 方法调用始终在纤程内部运行,它为 Node 事件循环回调样式提供了一个同步的 API。

您可以使用 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 将阻止 Node 事件循环,因此仅用于命令行实用程序等。

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

在网络服务器应用程序中,您确实不希望 Node 进程被 I/O 任务阻塞,因为这意味着它可能无法尽快响应客户端请求。

关于node.js - 在 fs.readFile() 的回调中使用 Email.send 时出现 Meteor "fiber"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32745353/

相关文章:

mysql - 在数据库中存储邮件的最佳方式(后缀)

ios - 使用 mailTo 将多个电子邮件地址发送到邮件应用程序

angularjs - "meteor mongo"与 "Error: EINVAL, invalid argument"崩溃

javascript - 如何将scrollIt 与Meteor 一起使用?

node.js - 如何通过 id 从 Firestore 获取?

javascript - 无法使用 JWT 读取 Express 上未定义的属性 'username'

node.js - redis-server - 找不到命令

php - 从电子邮件正文中删除 header

javascript - 无法弄清楚 mongod 和 nodejs 的 promise

node.js - 如何使用 node.js 通过 ListMatchingProducts API 访问 Amazon mws 中的 10 多个产品