1

我是 IronRouter 的新人,为什么 readFile 回调执行响应被发送到客户端。

Router.map(
  ()->
    this.route 'readFile',
      path: '/readFile'
      where: 'server'
      method: 'GET'
      action: ()->
        self = this
        fs.readFile '/tmp/a.txt', (err, data)->
          if err
            throw err
          console.log(data.toString())
          self.response.writeHead(200, {'Content-Type': 'text/plain'})
          self.response.end(data)
        console.log('response ...')

)

http.js:733
  W2049-12:04:26.781(8)? (STDERR)     throw new Error('Can\'t render headers after they are sent to the client.'
  W2049-12:04:26.781(8)? (STDERR)           ^
  W2049-12:04:26.782(8)? (STDERR) Error: Can't render headers after they are sent to the client.

但是,我使用 express ,这样效果很好。

exports.index = function(req, res){
  fs.readFile('/tmp/a.txt', function (err, data) {
    if (err) throw err;
    console.log(data.toString());
    res.send(200, data.toString());
  });
  console.log('response ...');
};

谢谢@ChristianF @Tarang 使用 Meteor._wrapAsync 或 Future 一切正常。当我使用自定义函数替换 fs.readFile 时。它需要 throw ex 。我怀疑我定义的函数有错误。如下:

@getAccounts = (callback) ->
 query = "SELECT Id, Name, AccountNumber FROM Account"
 queryBySoql(query, (err, result)->
   if err
     return console.error(err)
   return callback(result)
)

我调用了这个链接:

# using Meteor
#data = Meteor._wrapAsync(getAccounts)()


#using Future
waiter = Future.wrap(getAccounts)()
data = waiter.wait()
this.response.writeHead 200, {'Content-Type': 'text/plain'}
this.response.end JSON.stringify(data)

谢谢大家。

4

2 回答 2

3

就在今天,我在这个问题上苦苦挣扎。在我看来,答案是meteor(或至少是铁路由器)并没有像你期望的那样处理异步调用。解决方案是将异步调用包装到纤程中,这是流星用来保持编程同步的机制。

在你的情况下试试这个(对不起,我不太了解coffeescript):

var Future = Npm.require('fibers/future');
...
var waiter = Future.wrap(fs.readFile);
var data = waiter('/tmp/a.txt').wait();
response.writeHead(200, {'Content-Type': 'text/plain'})
response.end(data)

编辑解决问题的补充。

封装在 future 中的函数需要有一个回调作为最后一个带有 (err, result) 签名的参数。尝试这个:

@getAccounts = (callback) ->
 query = "SELECT Id, Name, AccountNumber FROM Account"
 queryBySoql(query, (err, result)->
   if err
     return console.error(err)
   return callback(err, result)
)
于 2013-11-25T04:52:37.487 回答
0

您可以将读取文件请求的回调包装到同一个光纤中。它不会阻止其他请求并且非常干净。

readFile = Meteor_wrapAsync(fs.readFile.bind(fs))
data = readFile("/tmp/a.txt")

console.log data
@response.writeHead(200, {'Content-Type': 'text/plain'})
@response.end data
return
于 2013-11-25T07:30:34.620 回答