我写了一个非常简单的函数,可以从给定的URL下载一个图像,调整其大小并上传到S3(使用'gm'和'knox'),我不知道我是否正确地将流读取到缓冲区.(一切正常,但这是正确的方式吗?)

另外,我想了解一些关于事件循环的信息,我如何知道函数的一次调用不会泄漏任何信息,或者将'buf'变量更改为另一个已经运行的调用(或者这种情况是不可能的,因为回调是匿名函数?)

var http = require('http');
var https = require('https');
var s3 = require('./s3');
var gm = require('gm');

module.exports.processImageUrl = function(imageUrl, filename, callback) {
var client = http;
if (imageUrl.substr(0, 5) == 'https') { client = https; }

client.get(imageUrl, function(res) {
    if (res.statusCode != 200) {
        return callback(new Error('HTTP Response code ' + res.statusCode));
    }

    gm(res)
        .geometry(1024, 768, '>')
        .stream('jpg', function(err, stdout, stderr) {
            if (!err) {
                var buf = new Buffer(0);
                stdout.on('data', function(d) {
                    buf = Buffer.concat([buf, d]);
                });

                stdout.on('end', function() {
                    var headers = {
                        'Content-Length': buf.length
                        , 'Content-Type': 'Image/jpeg'
                        , 'x-amz-acl': 'public-read'
                    };

                    s3.putBuffer(buf, '/img/d/' + filename + '.jpg', headers, function(err, res) {
                        if(err) {
                            return callback(err);
                        } else {
                            return callback(null, res.client._httpMessage.url);
                        }
                    });
                });
            } else {
                callback(err);
            }
        });
    }).on('error', function(err) {
        callback(err);
    });
};

推荐答案

总的来说,我没有看到任何会 destruct 你的代码的东西.

两个建议:

组合Buffer个对象的方式是次优的,因为它必须在每个"数据"事件上复制所有预先存在的数据.最好将这些块放在一个数组中,并将它们全部放在最后.

var bufs = [];
stdout.on('data', function(d){ bufs.push(d); });
stdout.on('end', function(){
  var buf = Buffer.concat(bufs);
})

为了提高性能,我会研究您使用的S3库是否支持流.理想情况下,您根本不需要创建一个大的缓冲区,而是直接将stdout流传递给S3库.

至于你问题的第二部分,那是不可能的.调用函数时,会为其分配自己的私有上下文,其中定义的所有内容都只能从该函数中定义的其他项访问.

使现代化

将文件转储到文件系统可能意味着每个请求占用的内存更少,但文件IO可能非常慢,因此可能不值得这么做.我想说的是,你不应该优化太多,直到你可以配置和压力测试这个功能.如果垃圾收集器正在执行其工作,则可能是过度优化.

尽管如此,还是有更好的方法,所以不要使用文件.由于您只需要计算长度,因此无需将所有缓冲区附加在一起即可计算长度,因此根本不需要分配新的缓冲区.

var pause_stream = require('pause-stream');

// Your other code.

var bufs = [];
stdout.on('data', function(d){ bufs.push(d); });
stdout.on('end', function(){
  var contentLength = bufs.reduce(function(sum, buf){
    return sum + buf.length;
  }, 0);

  // Create a stream that will emit your chunks when resumed.
  var stream = pause_stream();
  stream.pause();
  while (bufs.length) stream.write(bufs.shift());
  stream.end();

  var headers = {
      'Content-Length': contentLength,
      // ...
  };

  s3.putStream(stream, ....);

Node.js相关问答推荐

如何在CustomGPT的 node 中使用服务器端事件(SSE)

使用Moongose处理node.js中重定向的then()块链

在渲染上部署Node.js服务器时出错:MODULE_NOT_FOUND

如何在node.js中以随机顺序调用函数并按顺序操作

GitLab SAST中的Nodejcan未找到匹配项

Mongoose查询-如何根据当前查找ID获取其他集合并将其插入到当前查找中?

如何在Angular jest测试中调用Nodejs的垃圾收集? node v20的测试速度慢且内存泄漏

即使卷已设置,Docker Nodemon 也不会热重载

如何在 Firestore 函数上使用类型模型来获取字段值

express 和 mongoose 的新密码不正确

TypeError:在使用 Jest、Supertest、Express、Typescript 进行测试时无法读取未定义的属性(读取listen)

在 Node JS 中使用 url 链接而不是文件路径

如何在 MongoDB collection.find() 上获取回调

提供静态文件到底是什么意思?

Node JS:自动 Select `http.get`与`https.get`

使用 MongoDB 更新嵌套数组

在 Jade 包含中使用变量

Javascript在try块内设置const变量

在 Node.js 中获取终端的宽度

Firestore:多个条件 where 子句