异步GraphicsMagick For Node

Posted

技术标签:

【中文标题】异步GraphicsMagick For Node【英文标题】:Asynchronous GraphicsMagick For Node 【发布时间】:2013-07-19 10:48:43 【问题描述】:

我使用GraphicsMagick 作为节点。我基本上是裁剪照片并检索用户上传的照片的 exif 数据。我不想阻塞等待这些任务完成的请求流,因此我需要使用异步函数才能做到这一点。而且我认为我应该能够,因为这些是 node.js 自己进行异步的 I/O 操作。

但正如我所见,GraphicsMagick for node 中的所有函数都是同步函数。所以我无法确定如何实现我想要的。

我想到的一个想法是编写一个带有回调的函数,并在其中完成 GraphicsMagick 处理。并使用 .nextTick() 函数实现异步流。但我不完全确定这是否可以。 GraphicsMagick 也有任何异步函数。

请帮助我,非常感谢您提供有关如何从 graphicsmagick 获取异步函数的示例代码。

【问题讨论】:

【参考方案1】:

更新: @Saransh Mohapatra 的实际答案实际上是错误的。经过很少的调查后发现,所有对图像执行操作的方法实际上不执行任何操作,只是将参数附加到列表中,当您 write 或调用执行的任何缓冲区相关方法以获取/写入时将使用这些参数实际的图像缓冲区。

以下是blur 示例中的详细信息:

    我们打电话给blur:https://github.com/aheckmann/gm/blob/master/lib/args.js#L780 它调用this.out,它将调用:https://github.com/aheckmann/gm/blob/master/lib/command.js#L49 在构建时为它制定了哪些方法:https://github.com/aheckmann/gm/blob/master/lib/command.js#L34 它所做的一切 - a.push(arguments[i]); 然后将其连接到所有列表(到其他参数)。 就是这样。

那么当write被调用时:

    https://github.com/aheckmann/gm/blob/master/lib/command.js#L62 它得到参数列表self.args(): https://github.com/aheckmann/gm/blob/master/lib/command.js#L78 仅过滤掉一些保留字段:https://github.com/aheckmann/gm/blob/master/lib/command.js#L274 那么这些参数将被加入到_spawn 中,它是从write 调用的:https://github.com/aheckmann/gm/blob/master/lib/command.js#L187 就是这样。

因此,基于此,任何使operations 覆盖图像的方法,但不保存或保留它的缓冲区 - 不需要任何异步,因为它们实际上根本不做任何工作。 所以这意味着 - 你确实需要担心它们。

旧: 对于任何繁重的处理工作,最好的方法是使用单独的进程。 您可以创建另一个小型 node.js 进程,它将与主进程具有一些 通信 能力(ZeroMQ 在这里是不错的选择)。

必须通知这个单独的进程有关文件(路径)以及如何处理它,您可以轻松地从通过 ZeroMQ 做出此类决定的主进程发送该数据。

这种方法将允许您在主(Web?)节点进程的工作方式上具有独立,并且将来可以扩展到单独的硬件/实例。 这也是非常好的做法(类unix应用程序逻辑分离)。

【讨论】:

zeromq 是某种排队服务吗?如果是,那么我不是在寻找那个。我不相信是繁重的处理。 ZeroMQ 是供内部使用的简单套接字消息传递系统(它不是真正的消息队列)。这个想法不是将作业排队,而是将它们从主进程中移除,以防止大量的图像处理阻塞。图像处理或任何类型的内容生成/渲染(如 pdf、重新压缩、调整大小)是繁重的过程,应独立于 Web 服务进行处理。 好的。但是我仍然不明白如果使用 ZeroMQ 关闭主进程,而我可以在节点本身中完成它,那么需要什么。 Node.js 有这个内置的用于异步处理 I/O 密集型工作。 你写到 GraphicsMagic 函数是同步的。 是的……这就是我想知道的。如何将同步函数转换为异步函数。【参考方案2】:

这是承诺 gm 的方法:

var Promise = require('bluebird');
var gm = require('gm').subClass(imageMagick: true);
Promise.promisifyAll(gm.prototype);

gm('1.jpg')
  .resize(240, 240)
  .noProfile()
  .writeAsync('1b.jpg')
  .then(function () 
    console.log('done');
  );
  .catch(function (err) 
    console.log(err);
  );

https://github.com/aheckmann/gm/issues/320

【讨论】:

【参考方案3】:

抱歉,我的观察有误,虽然 GraphicsMagick 模块看起来是同步函数,但实际上并非如此。每次操作完成时,它们都会产生子进程。这已经被确认here。

所以其他任何人都在寻找这个问题,GraphicsMagick 函数是异步的。而且您不必做任何事情。它是一个非常好的模块,值得一试。

谢谢。

【讨论】:

这个答案实际上是错误的,因为在我的答案中调查后,我发现这些操作根本没有做任何工作,而只是在列表中添加参数,这是 after 使用时writeing 或获取图像缓冲区。所以只有在最后一点 - 子进程才会产生。 Graphicsmagick 使用 imagemagick 或其他任何东西来实际处理图像,因此它必须分叉一个进程并等待分叉异步响应,对吧?

以上是关于异步GraphicsMagick For Node的主要内容,如果未能解决你的问题,请参考以下文章

在node.js和GraphicsMagick中将tiff转换为jpeg

Node.JS:forEach 与 for 循环异步性质

Node.js/Mongoose 等待异步 For 循环

如何在 AWS Lambda 上安装 GraphicsMagick 或 ImageMagick?

node.js里的forEach也是异步的吗

node入门异步 和promise