2017-07-18 90 views
2

相对较新的node.js和异步处理方式,到目前为止我已经能够使用promise读取使用fs readFile的文件,但我没有'没有任何运气让zlib Gunzip工作。写作的CoffeeScript:Node.js - Gunzip已读文件异步问题

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

promisfyRun是有前途的一个单一的功能(我没有写出来,但它的工作)。我已经设法成功地使用它的fs.readFile组件,就像这样:

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

这只是正常,等待要打开的文件,然后继续。 'data'包含文件的主体。我认为它应该是一个非常合理的扩展,以纳入gunzip组件,但到目前为止这一直是一个挑战。

我看了几个npm gunzip模块。似乎最有趣的那个是gunzip-maybezlib.Gunzip(我在这里尝试)。

对于这种特殊情况下的错误消息已:

"Unhandled rejection Error: Can't set headers after they are sent."

我认为这是相关的过程中就已经有其异步的完成事业

更新 - 全堆栈跟踪:

Unhandled rejection Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:357:11) at ServerResponse.header (/Users/jcook/project/node_modules/express/lib/response.js:725:10) at ServerResponse.send (/Users/jcook/project/node_modules/express/lib/response.js:170:12) at ServerResponse.json (/Users/jcook/project/node_modules/express/lib/response.js:256:15) at ServerResponse.send (/Users/jcook/project/node_modules/express/lib/response.js:158:21) at /Users/jcook/project/.tmp/lib/util.js:40:22 at 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) at 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) at Async._drainQueues (/Users/jcook/project/node_modules/bluebird/js/release/async.js:143:10) at Immediate.Async.drainQueues (/Users/jcook/project/node_modules/bluebird/js/release/async.js:17:14) at runCallback (timers.js:672:20) at tryOnImmediate (timers.js:645:5) at processImmediate [as _immediateCallback] (timers.js:617:5)

+0

什么是完整的堆栈跟踪? – LEQADA

+0

请发送发送标题的代码。你的'util。tryCatcher'(或使用它的代码)可能是问题。 – Bergi

回答

1

当你看到Can't set headers after they're sent,它几乎始终是因为您的请求处理程序在端点响应后仍在执行,其中的IME与不等待回调完成的代码有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 

其次,您从回调中运行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() 

这不起作用,因为什么东西被从承诺返回是异步的。您需要处理响应异步:

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的土地,你就可以使用ES6异步/ AWAIT:

data = await run() 
+0

这太棒了!感谢这样一个彻底的答复,我刚刚了解到承诺,我认为这让我有点头脑围绕他们的预期效用。 – cookersjs

0

一个简单而有效的方法是使用fs和zlib模块我节点:

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

+0

我试过了第一个选项,但是我收到一条消息说'TypeError:fs.​​createReadStream(...)。pipe不是函数' – cookersjs