node.js - 为什么 Express 的默认错误处理程序在从 Readable 流发出时捕获错误?

标签 node.js express stream streaming

我使用命令行 expressstream_test 安装了样板 Express 应用程序。我将默认的 /routes/index.js 替换为:

var express = require('express');
var router = express.Router();
var ReadFile = require('./readFile.js');

/* GET home page. */
router.get('/', function(req, res, next) {
  var readFile = ReadFile();
  readFile
  .on('data', function(data) {
    res.write(data);
  })
  .on('end', function() {
    res.end();
  })
  .on('error', function(err) {
    console.log(err);
  });
});

module.exports = router;

readFile.js 只是 fs.createReadStream 的简单包装:

var Readable = require('stream').Readable;
var util = require('util');
var fs = require('fs');

function ReadFile(options) {
  if (!(this instanceof ReadFile)) {
    return new ReadFile(options);
  }
  Readable.call(this);

  options = options || {};

  var self = this;

  fs.createReadStream('pride_and_prejudice.txt')
  .on('data', function(data) {
    self.push(data);
  })
  .on('end', function(end) {
    self.push(null);
  });

}

util.inherits(ReadFile, Readable);
ReadFile.prototype._read = function _readGetDeals() {};

module.exports = ReadFile;

这完全没问题。调用路由时,会将pride_and_prejudice.txt的内容输出到屏幕。

但是假设某些要求未得到满足,并且我想在传输数据之前抛出错误:

var Readable = require('stream').Readable;
var util = require('util');
var fs = require('fs');

function ReadFile(options) {
  if (!(this instanceof ReadFile)) {
    return new ReadFile(options);
  }
  Readable.call(this);

  options = options || {};

  var self = this;

  if (!options.okay) {
    return self.emit('error', new Error('Forced crash'));
  }

  fs.createReadStream('pride_and_prejudice.txt')
  .on('data', function(data) {
    self.push(data);
  })
  .on('end', function(end) {
    self.push(null);
  });

}

options.okayfalse 时,会引发错误强制崩溃。。我希望在监听 error 时捕获 index.js 路由中的错误。但处理程序永远不会执行。令我非常惊讶的是 app.js 中的默认错误处理程序正在捕获错误:

if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

这让我发疯。错误是如何结束的?为什么事件监听器没有捕获它?

最佳答案

我的想法是,即使在流对象创建完成之前,也会发出“错误”事件。因此, Node 找不到您附加的“错误”监听器,因为它尚未创建,并将其作为未处理的“错误”事件抛出。

一种解决方案是使用 setImmediate 延迟事件发出。然后它将创建流对象并在发出错误之前首先绑定(bind)错误监听器:

 if (!options.okay) {
    setImmediate(function(){ 
      self.emit('error', new Error('Forced crash')); 
    });
    return;
  }

关于node.js - 为什么 Express 的默认错误处理程序在从 Readable 流发出时捕获错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31762728/

相关文章:

javascript - Dropping Collection后,保存第一条记录时重新创建了Collection,但为什么它的索引没有?

c++ - 使用 stream_iterator 分块读取文件

python - 如何使用 python 结构发送流

node.js - 未处理的 promise 拒绝警告 : Error: Cannot find module '/MyProject/node_modules/react-native-scripts/build/scripts/init.js'

node.js - 在 Docker 容器中打开端口

javascript - 从本地主机调用 api 的生产环境

javascript - 使用 Express 路由器在浏览器中获取 "Cannot GET/"

java - 流式传输 2d 数组、修剪值并收集回 2d 数组

node.js - 设置 AWS Lambda 调用的 LogStreamName

javascript - 如何将嵌套回调转换为 promise