Node.js - Gunzip 一个已经读取的文件异步问题
Node.js - Gunzip an already read file async issues
相对较新 node.js 和异步处理方式,到目前为止,我已经能够使用 promises 来使用 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 是为了承诺一个单一的功能(我没有写,但它确实有效)。我已经成功地将它用于 fs.readFile 组件,如下所示:
promisifyRun(fs, 'readFile', filepath, 'utf-8')
.then (data) ->
return data
.catch respondError res
这工作得很好,它等待文件打开然后继续。 'data' 包含文件的主体。我认为合并 gunzip 组件应该是一个非常合乎逻辑的扩展,但到目前为止这一直是一个挑战。
我看过几个 npm gunzip 模块。最有趣的是 gunzip-maybe or zlib.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)
一个简单有效的方法是使用 node 附带的 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
当您看到 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
来自回调内部。我的猜测是您正在尝试在另一侧使用 return 值,如下所示:
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 return 编辑的内容是异步的。您需要处理异步响应:
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 async/await:
data = await run()
相对较新 node.js 和异步处理方式,到目前为止,我已经能够使用 promises 来使用 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 是为了承诺一个单一的功能(我没有写,但它确实有效)。我已经成功地将它用于 fs.readFile 组件,如下所示:
promisifyRun(fs, 'readFile', filepath, 'utf-8')
.then (data) ->
return data
.catch respondError res
这工作得很好,它等待文件打开然后继续。 'data' 包含文件的主体。我认为合并 gunzip 组件应该是一个非常合乎逻辑的扩展,但到目前为止这一直是一个挑战。
我看过几个 npm gunzip 模块。最有趣的是 gunzip-maybe or zlib.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)
一个简单有效的方法是使用 node 附带的 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
当您看到 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
来自回调内部。我的猜测是您正在尝试在另一侧使用 return 值,如下所示:
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 return 编辑的内容是异步的。您需要处理异步响应:
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 async/await:
data = await run()