2

我一直在尝试像这样将 gm 与 Bluebird 一起使用:

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 AM web.1 | 在 toBuffer (/Users/danielrvt/IdeaProjects/twe-backend/node_modules/gm/lib/command.js:162:17)

如果我不使用承诺,它就可以正常工作。

4

1 回答 1

3

这并不是你应该如何使用该gm模块的方式,因为它旨在提供一个工厂gm()和许多可级联的 mutator 函数,例如.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'); 

或者,如果你真的,真的很想使用 Promises...

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()));

再一次,更多的打字和复杂性都是为了使用最新的“闪亮”的东西。;)

于 2016-11-26T14:04:23.893 回答