NodeJS / gm:异步调用的Promise

时间:2017-09-08 11:46:51

标签: javascript node.js asynchronous promise gm

我使用gm来操作nodeJS应用程序中的一些图像。这就是我的功能。

正如你所看到的那样,有一些操纵开关(在这个例子中:旋转)。已创建gmStream,并且将使用切换.stream()pipe()。 到目前为止一切都很好。

但是对于切换案例resize,我需要知道图像的尺寸,我通过size()得到。但这是一个异步调用。 如果gmStream未用于交换机下方显示的stream()。但是在这个stream()中会有更多的DB内容,所以我需要使用相同的东西......

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)
        })
      })
  })
}

1 个答案:

答案 0 :(得分:2)

你可能希望将Promise链接在一起以完成你所追求的目标。如果你将你的开关案例中的逻辑分解为Promise-returns函数,你可能会得到类似以下内容的东西(免责声明:我从未使用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)
        })
      })
    })
  })
}
相关问题