NodeJS / gm:承诺asynchronous调用

我使用gm来操作nodeJS应用程序中的一些图像。 这是我的function如何。

正如你所看到的,有一些操作开关(在这个例子中:旋转)。 gmStream被创build,在切换之后.stream()pipe()将被使用。 到目前为止,一切都很好。

但是,对于切换resize的情况下,我需要知道图像的尺寸,我通过size() 。 但是这是一个asynchronous调用。 这个gmStream不用于交换机下面显示的stream() 。 但是在这个stream()会做更多的数据库的东西,所以我需要使用相同的东西…

 function manipulate (method, param) { return new Promise(function (resolve, reject) { // Configure GridFS (gridfs-stream) const gfs = Grid( MongoInternals.defaultRemoteCollectionDriver().mongo.db, MongoInternals.NpmModule ) switch (method) { case 'rotate': gmStream = gm(readStream) .rotate('#ffffff', param.rotate) break // ... some more cases ... case 'resize': gmStream = gm(readStream) .size(function (err, size) { if (!err && size.width >= 1000 && size.height >= 1000) { gmStream.resize('1000').stream().pipe(writeStream) // <-- should use the stream call below, as there has to be done some DB manipulation... } }) break } // resize case should also use this part... gmStream .stream(function (err, stdout, stderr) { gfs.findOne({ _id: sourceId }, function (err, file) { const writeStream = gfs.createWriteStream({ metadata: { } }) writeStream.on('close', function (newFile) { resolve(newFile) } ) stdout.pipe(writeStream) }) }) }) } 

您可能希望将Promises链接在一起,以完成您的工作。 如果你将开关盒中的逻辑分解成Promise返回函数,你可能会得到类似下面的工作(免责声明:我从来没有使用gm ,我不熟悉它的API)。

 function rotate (readStream, rotate) { return new Promise(function (resolve, reject) { resolve(gm(readStream).rotate('#ffffff', param.rotate)) }) } function resize (readStream, writeStream) { return new Promise(function (resolve, reject) { var gmStream = gm(readStream) gmStream.size(function (err, size) { if (err) { return reject(err) } if (size.width >= 1000 && size.height >= 1000) { gmStream.resize('1000').stream().pipe(writeStream) resolve(gmStream) } }) }) } function handleManipulation (args) { return new Promise(function (resolve, reject) { // This will be a Promise for the base gmStream object to work with var gmStream; // Not sure where this comes from, so here's a placeholder var readStream = ...; // You were doing this for every case, so I don't think putting it here // will cause you any grief, but it's a resource to clean up if the // Promise gets rejected, so keep that in mind const writeStream = gfs.createWriteStream({ metadata: { } }) // Figure out which method to create a Promise'd object for switch (args.method) { case 'rotate': gmStream = rotate(readStream, ...) // I'm not sure what the value of // the `rotate` argument should be break case 'resize': gmStream = resize(readStream, writeStream) break } // We wait for the gmStream Promise to resolve before proceeding. gmSteam.then(function (stream) { stream.stream(function (err, stdout, stderr) { if (err) { return reject(err) } gfs.findOne({ _id: sourceId }, function (err, file) { if (err) { return reject(err) } writeStream.on('close', function (newFile) { resolve(newFile) } ) stdout.pipe(writeStream) }) }) }) }) }