Node.js – Gunzip已读文件的asynchronous问题

相对较新的node.js和asynchronous的做法,到目前为止,我已经能够使用承诺阅读文件使用fs readFile,但我没有任何运气让zlib Gunzip工作。 用Coffeescript写作:

promisifyRun(fs, 'readFile', filepath, 'utf-8') .then (file) -> promisifyRun(zlib, 'Gunzip', file) .then (data) -> console.log "HELLO" return data .catch respondError res 

promisfyRun是承诺一个单一的function(我没有写,但它的确工作)。 我已经成功地将它用于fs.readFile组件,如下所示:

  promisifyRun(fs, 'readFile', filepath, 'utf-8') .then (data) -> return data .catch respondError res 

这工作得很好,它等待文件被打开,然后继续。 'data'包含文件的主体。 我认为它应该是一个非常合乎逻辑的扩展,将枪支组件纳入其中,但迄今为止这一直是一个挑战。

我看了几个npm gunzip模块。 看起来最有趣的是gunzip-或者zlib.Gunzip (我在这里尝试)。

这个特定情况的错误信息是:

“未处理的拒绝错误:发送后无法设置标题”。

我认为这与已经完成的asynchronous性原因有关

更新 – 全堆栈跟踪:

未处理的拒绝错误:发送后无法设置标题。 ServerResponse.send(/ Users / jcook)上ServerResponse.header(/Users/jcook/project/node_modules/express/lib/response.js:725:10)处的ServerResponse.OutgoingMessage.setHeader(_http_outgoing.js:357:11) /Project/node_modules/express/lib/response.js:170:12)在ServerResponse.json(/Users/jcook/project/node_modules/express/lib/response.js:256:15)ServerResponse.send(/ Users /jcook/project/node_modules/express/lib/response.js:158:21)在/Users/jcook/project/.tmp/lib/util.js:40:22在tryCatcher(/ Users / jcook / project / node_modules /bluebird/js/release/util.js:16:23)at Promise._settlePromiseFromHandler(/Users/jcook/project/node_modules/bluebird/js/release/promise.js:512:31)at Promise._settlePromise(/ Users /jcook/project/node_modules/bluebird/js/release/promise.js:569:18)在Promise._settlePromise0(/Users/jcook/project/node_modules/bluebird/js/release/promise.js:614:10)at Promise._settlePromises(/Users/jcook/project/node_modules/bluebird/js/release/promise.js:689:18)at Async._drainQueue(/ Users / jcook / project / node_modules / bluebird / js / release / async.js:133:16)Async._drainQueues(/Users/jcook/project/node_modules/bluebird/js/release/async.js:143:10)在run.all.Async.drainQueues(/Users/jcook/project/node_modules/bluebird/js/release/async.js:17:14)上的runCallback(timers.js:672:20),在tryOnImmediate(timers.js:645: 5)at processImmediate [as _immediateCallback](timers.js:617:5)

Can't set headers after they're sent ,几乎总是因为请求处理程序在端点响应后仍然在执行,而IME与不等待callback完成的代码有99%的相关性。

首先,你不否认使用诺言的许多好处。

 promisifyRun(fs, 'readFile', filepath, 'utf-8') .then (file) -> // Just return another promise here. return promisifyRun(zlib, 'Gunzip', file) .then (data) -> console.log "HELLO" return data .catch respondError res 

其次,你从callback中运行return data 。 我的猜测是,你正试图在另一边使用返回值,如下所示:

 run = ()-> promisifyRun(fs, 'readFile', filepath, 'utf-8') .then (file) -> // Just return another promise here. return promisifyRun(zlib, 'Gunzip', file) .then (data) -> console.log "HELLO" return data .catch respondError res myData = run() 

这是行不通的,因为从promise中返回的是asynchronous的。 您需要处理asynchronous响应:

 run = ()-> promisifyRun(fs, 'readFile', filepath, 'utf-8') .then (file) -> // Just return another promise here. return promisifyRun(zlib, 'Gunzip', file) // We remove the rest of the function, // so it just returns the promise above. run().then (data)-> console.log data 

一旦CS 2.0登陆,你就可以使用ES6asynchronous/等待:

 data = await run() 

一个简单而有效的方法是使用节点附带的fs和zlib模块进行stream式处理:

 fs.createReadStream('./file.gz') .pipe(zlib.createGunzip()) .pipe(res); 

如果你的情况你只有文件内容的缓冲区,那么zlib.gunzip就足够了:

 zlib.gunzip(buffer, (err, gunzippedBuffer) => { // ... }); 

请参阅https://nodejs.org/dist/latest-v6.x/docs/api/zlib.html#zlib_zlib_gunzip_buf_options_callback