异步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 使用时write
ing 或获取图像缓冲区。所以只有在最后一点 - 子进程才会产生。
Graphicsmagick 使用 imagemagick 或其他任何东西来实际处理图像,因此它必须分叉一个进程并等待分叉异步响应,对吧?以上是关于异步GraphicsMagick For Node的主要内容,如果未能解决你的问题,请参考以下文章
在node.js和GraphicsMagick中将tiff转换为jpeg