Javascript 将节点gm与承诺和缓冲区一起使用
我一直在尝试将转基因技术用于蓝鸟,如下所示:Javascript 将节点gm与承诺和缓冲区一起使用,javascript,node.js,promise,gm,Javascript,Node.js,Promise,Gm,我一直在尝试将转基因技术用于蓝鸟,如下所示: var gm = require('gm'); var bluebird = require('bluebird'); gm = bluebird.promisifyAll(gm); gm(req.file.buffer) .crop(tWidth, tHeight, tWidth/2, tHeight/2) .gravity('Center') .toBuffer() .then(...) 但是,当我尝试这样的
var gm = require('gm');
var bluebird = require('bluebird');
gm = bluebird.promisifyAll(gm);
gm(req.file.buffer)
.crop(tWidth, tHeight, tWidth/2, tHeight/2)
.gravity('Center')
.toBuffer()
.then(...)
但是,当我尝试这样的事情时:
var gm = require('gm');
var bluebird = require('bluebird');
gm = bluebird.promisifyAll(gm);
gm(req.file.buffer)
.crop(tWidth, tHeight, tWidth/2, tHeight/2)
.gravity('Center')
.toBuffer()
.then(...)
我得到这个错误:
gm().toBuffer()需要回调
如果我只承诺缓冲区方法:
bluebird.promisify(gm(req.file.buffer)
.crop(tWidth, tHeight, tWidth/2, tHeight/2)
.gravity('Center')
.toBuffer)()
.then(buff => {...})
我得到这个错误:
TypeError:this.stream不是函数
上午6:36:21 web.1 |在toBuffer(/Users/danielrvt/IdeaProjects/twe backend/node_modules/gm/lib/command.js:162:17)
如果我不使用Promissions,它就可以正常工作。这并不是你应该如何使用
gm
模块,因为它的设计目的是提供一个工厂gm()
和许多可级联的变异函数,如.resize()
Bluebird的.promisifyAll()
仅适用于接受回调的函数,而大多数gm
的函数不接受回调
如果您希望使用带有承诺的gm
,您需要通过将通话包装为
function mutateAndSave() {
return new Promise( function(resolve,reject) {
try {
gm(image)
.doSomething()
.write(outputPath, function(err) {
if(err) {
throw(err);
}
resolve();
});
}
catch (err) {
reject(err);
}
});
}
之后,你可以
mutateAndSave()
.then(...)
.catch(...);
更新
这里有两种方法来做你想做的事,但是
您会注意到,两者都比仅使用gm
要复杂得多
下面是一种使用事件状态机执行所需操作的方法
const gm = requre('gm');
const EventEmitter = require('events');
const input_path = './image.jpg'
const output_path = './newimage.jpg';
const worker = new EventEmitter(); // create an event worker
// define the worker states - note: NO error checking! Muy mal!
const event_states={
start:() => worker.emit('resize',gm(input_path)), // creates a new gm image instance
resize:(img) => worker.emit('crop', img.resize(100,100)), // resizes the image
crop:(img) => worker.emit('write', img.crop(2,2,50,50)), // crops it
write:(img) => { // and writes it to the filesystem
img.write(output_path, err => {
if(err) {
worker.emit('error',err);
return;
}
worker.emit('complete');
});
},
error: (err) => console.error(err.toString()), // report error
complete: () => console.log('complete') // alert on completion
};
// add the states to the worker as event handlers
Object.keys(event_states).forEach(k => worker.on(k, event_states[k]));
// and fire it up...
worker.emit('start');
或者如果你真的,真的想用承诺
const writer = function (img) {
return new Promise( (resolve, reject) => {
img.write(output_path,err => {
if(err) {
reject(err);
return;
}
resolve(true);
});
});
};
const reader = function (input_path) {
return new Promise( (resolve,reject) => {
let img;
try {
img = gm(input_path);
}
catch (err) {
reject(err);
return;
}
resolve(img);
});
};
reader('./image.jpg')
.then( img => { return img.resize(100,100) }) // the return here is for illustration only
.then( img => img.crop(2,2,50,50)) // since this does exactly the same thing with less typing!
.then( writer )
.then( res => console.log('complete'))
.catch( err => console.error(err.toString()));
同样,更多的输入和复杂性都是为了使用最新的“闪亮”的东西 在这一点上,只使用设计好的模块似乎要容易得多。实际上,我想在一个图像缓冲区上执行10个以上的操作,所以我考虑使用
Promise.all([gmPromises])
。在这种情况下,使用承诺真的让一切变得简单多了。是的……但是通用汽车并不是为了支持承诺而写的,所以你需要“找到另一种方式”。)在新承诺
回调中使用try
/catch
是毫无意义的。@RobRaisch否决不是因为代码不够简洁,而是因为它不起作用并且暗示了错误的功能。异步函数(应该)永远不会同步抛出,因此没有必要使用try
/catch
。只有当回调出现错误时,您才需要调用reject
,但是您没有这样做,而是throw
它(导致uncaughtException
)。在您的帖子中唯一一个好的提示是writer
promisifyAll
创建一个.toBufferAsync()
函数,该函数将返回承诺。您需要调用该函数,而不是.toBuffer()
。您的promisify
方法不起作用,因为toBuffer
函数对实例起作用。@Bergi下次您可能希望在注释之前实际尝试该代码,然后建议使用.toBufferAsync()由于我在回答中提供的原因,
不起作用。@RobRaisch当然(考虑到toBuffer
接受回调),我看不出你的回答中有任何理由不起作用?@Bergi,也许你想提供一个使用蓝鸟promisifyAll()
的工作示例?