1

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

如您所见,有一个用于某些操作的开关(在此示例中:旋转)。gmStream被创建并在切换之后.stream()pipe()被使用。到目前为止一切都很好。

但是对于 switch case resize,我需要知道图像的尺寸,我确实通过size(). 但这是一个异步调用。这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)
        })
      })
  })
}
4

1 回答 1

2

您可能希望将 Promises 链接在一起以完成您所追求的。如果您将 switch 案例中的逻辑分解为 Promise-returning 函数,您可能会得到类似以下的工作(免责声明:我从未使用过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)
        })
      })
    })
  })
}
于 2017-09-09T14:50:09.847 回答