简体   繁体   English

NodeJS / gm:允许异步调用

[英]NodeJS/gm: Promises with asynchronous calls

I'm using gm to manipulate some images in my nodeJS application. 我正在使用gm处理我的nodeJS应用程序中的某些图像。 This is how my function looks like. 这就是我的功能。

As you can see there is a switch for some manipulation (in this example: rotation). 如您所见,这里有一个用于某些操作的开关(在此示例中:旋转)。 gmStream is created and after the switch .stream() and pipe() will be used. 创建gmStream并在使用.stream()pipe()开关之后。 So far everything is fine. 到目前为止,一切都很好。

But for the switch case resize , I need to know the dimensions of the image, which I do get via size() . 但是对于开关盒的resize ,我需要知道图像的尺寸,这确实是通过size() But this is an asynchronous call. 但这是一个异步调用。 With this gmStream isn't used for the stream() shown below the switch. 使用此gmStream它不会用于开关下方显示的stream() But there will be done some more DB stuff in this stream() , so I need to use the same thing... 但是在这个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)
        })
      })
  })
}

You may want to chain Promises together to accomplish what you're after. 您可能需要将Promises链接在一起,以完成自己的工作。 If you break apart the logic in your switch case into Promise-returning functions, you might be able to get something like the following to work (disclaimer: I've never used gm and I'm not familiar with its API). 如果您将开关案例中的逻辑分解为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)
        })
      })
    })
  })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM