具有gm,缓冲区和承诺的Node中的随机行为

时间:2015-03-07 00:41:29

标签: node.js buffer q graphicsmagick

我最近将图像保存模块切换到gm(grahicsmagick)并开始使用缓冲区而不是保存到磁盘。

我期望的输出是一个带有md5哈希的数组,然后是原始图像和缩略图的路径。我使用承诺,像这样。

saveOrig( imageUrl )
.then( saveThumb )
.then( function( image ) {
    var returnArray = [ image.hash, image.orig, image.thumb ]
    console.log( returnArray )
    resolve( returnArray )
})
.catch( function( error ) {
    reject( new Error( error.message ) )
})

这是第一个函数,下一个函数几乎相同

function saveOrig ( imageUrl ) {
    return Q.Promise( function ( resolve, reject, notify ) {

        var image = {
            extension: path.extname( imageUrl )
        }

        gm( request( imageUrl ) )
            .format( function( err, value ) {
                if ( err ) return reject ( new Error ( err ) )

                image.type = value
            })
            .stream( image.type, function ( err, stdout, stderr ) {
                if ( err ) return reject( new Error( err ) )

                var bufs = []

                stdout.on( 'data', function ( d ) {
                    bufs.push( d )
                })

                stdout.on( 'end', function () {
                    var buf = Buffer.concat( bufs )

                    image.hash = crypto.createHash( 'md5' ).update( buf ).digest( 'hex' )

                    console.log ( image.hash )

                    uploader = s3Client.putBuffer( buf, type + "/" + image.hash + "-orig" + image.extension, {
                        'Content-Length': buf.length,
                        'Content-Type': 'image/jpeg'
                    }, function ( err, result ) {
                        if ( err ) return reject( new Error( err ) )

                        if ( result.statusCode == 200 ) {
                            image.orig = uploader.url

                            resolve( image )
                        }
                    })
                })
            })
    })
}

再次,这是我期望看到的,

[ '820f841a0a7cdc854b70f8b534dc7705',
'https://my-amazon-bucket.s3.amazonaws.com/read/820f841a0a7cdc854b70f8b534dc7705-orig.jpeg',
'https://my-amazon-bucket.s3.amazonaws.com/read/820f841a0a7cdc854b70f8b534dc7705-thumb.jpeg' ]

当我处理一个图像时会发生这种情况。但是,当我将此函数调用映射到具有Q.all的数组时,我会得到极其随机的混合哈希,缩略图和原始路径,可能来自其之前对该函数的其他调用。

在我没有使用缓冲区或gm之前,我没有这种行为。这是什么原因?


编辑:这是我如何调用上述saveImage函数。当我将项目保存到磁盘,然后使用easy-image模块操作它们时,这似乎工作正常。

images = window.document.getElementsByTagName( 'img' )

imageMapFunction = Array.prototype.map.call( images, function ( each, index ) {
    return Q.promise( function ( resolve, reject, notify ) {


    saveImage( req.body.type, each.src )
    .spread( function ( imageHash, imageOriginalPath, imageThumbPath ) {
        article.images.push({
            image: imageOriginalPath,
            imageHash: imageHash,
            imageThumb: imageThumbPath
        })

        each.src = imageOriginalPath

        resolve()
    })

    })
})

Q.all( imageMapFunction )
.then( function () {

2 个答案:

答案 0 :(得分:1)

Console.log是异步;因此它会以异步顺序吐出内容,因此根据当前正在记录的内容,它很容易出错。

如果你真的必须通过控制台跟踪它;使用console.error,因为它是同步的;或使用一个简单的数组来推动一切;然后在最后注销该数组。

答案 1 :(得分:1)

此部分不正确:

uploader = s3Client.putBuffer( buf, type + "/" + image.hash + "-orig" + image.extension, {
    'Content-Length': buf.length,
    'Content-Type': 'image/jpeg'
}, function ( err, result ) {
    if ( err ) return reject( new Error( err ) )

    if ( result.statusCode == 200 ) {
        image.orig = uploader.url

        resolve( image )
    }
});

您需要var作为var uploader

就像现在一样,如果你多次调用你的函数,你每次都会覆盖一个全局uploader,所以你得到的最终结果将取决于每个图像处理的时间和它们的持续时间上传。