流读取在nodejs中返回空

Stream read returning empty in nodejs

我正在使用 express 创建一个 Web 服务,它将从流中读取字符串数据,并使用该值响应 HTTP POST 请求。这是定义 readFileFromS3(.) 函数的 S3Store.js 文件的代码:

S3Store.js

S3Store.prototype.readFileFromS3 = function(filename, callback) {
var readConfig = {
    'Bucket': 'shubham-test',
    'Key': filename
};
var readStream = this.s3.getObject(readConfig).createReadStream();
var allData = '';

readStream.on('data', function(data) {
    //data = Buffer.concat([allData, data]);
    data = allData + data;
    console.log("data: " + data);
});

readStream.on('error', function(err) {
    callback(err, null);
});

现在,如果我从这样的终端调用此方法:

s3Instance.readFileFromS3('123.json', function(err, data) {
    console.log(data);
});

我看到 data 的相应字符串已记录到控制台。但是,当我从 routes 中的一个内部为 HTTP POST 请求调用相同的方法时,服务响应 data 的值设置为空字符串。 POST 请求的代码:

router.post('/resolve', function(req, res) {
    var commandJson = req.body;

    var appId = commandJson['appId'];
    var command = commandJson['text'];

    if (appId == undefined || command == undefined) {
        res.status(400).send("Malformed Request: appId: " + appId + ", command: " + command);
    };

    s3Store.readFileFromS3('123.json', function(err, data) {
        res.send(data);
    });
});

为什么从 HTTP POST 方法调用 readFileFromS3(.) 时 return 是一个空字符串,而不是当我直接从节点控制台 运行 调用相同的方法时?

您正在记录数据,但没有将任何内容传递给完成回调(更多解释请参见下文):

S3Store.prototype.readFileFromS3 = function(filename, callback) {
  var readConfig = {
      'Bucket': 'shubham-test',
      'Key': filename
  };
  var readStream = this.s3.getObject(readConfig).createReadStream();
  var allData = [];

  // Keep collecting data.
  readStream.on('data', function(data) {
    allData.push(data);
  });

  // Done reading, concatenate and pass to completion callback.
  readStream.on('end', function() {
    callback(null, Buffer.concat(allData));
  });

  // Handle any stream errors.
  readStream.on('error', function(err) {
    callback(err, null);
  });
};

我冒昧地重写了数据收集以使用缓冲区而不是字符串,但这显然不是必需的。

callback 参数是一个完成函数,意味着在完成读取 S3 流或引发错误时调用。错误处理已经到位,但不是在读取流中的所有数据时回调的部分,这就是我添加 end 处理程序的原因。

此时,readStream 已用尽(其中的所有内容都已读入 allData),当收集到的数据 作为第二个参数时调用完成回调.

整个 Node 的常见习惯是完成回调接受(至少)两个参数:第一个是错误,或者 null 当没有错误时,第二个是你想要的数据传递回调用者(在您的情况下,是调用 res.send() 的路由处理程序中的匿名函数)。