ES8 TypeScript如何等待可读流完成 解决fs解压gz文件提前执行问题
问题根因
你当前代码的核心问题是:stream.pipe() 方法返回的是流对象本身,并非Promise实例,因此代码中的await没有任何等待效果,函数会在流启动后立刻返回,自然会出现解压未完成就执行后续逻辑的问题。
异步方案(推荐,不阻塞事件循环,适合大文件)
将整个流的生命周期封装到Promise中,通过监听流的事件来变更Promise状态,即可实现正确的异步等待:
import { createGunzip } from 'zlib'; import { createReadStream, statSync, createWriteStream } from 'fs'; function fileExists(filePath: string) { try { return statSync(filePath).isFile(); } catch (err) { return false; } } function gunzipFile(source: string, destination: string): Promise<void> { return new Promise((resolve, reject) => { if (!fileExists(source)) { return reject(new Error(`the source: ${source} does not exist`)); } const src = createReadStream(source); const dest = createWriteStream(destination); src.pipe(createGunzip()) .pipe(dest) // 写入流完成所有写入操作后触发finish事件,代表解压全部完成 .on('finish', () => { resolve(); }) // 任意环节出错直接抛出 .on('error', (error) => { // 可在此处添加自定义错误日志逻辑 reject(error); }); }); }
调用时添加await即可保证后续逻辑在解压完成后执行:
async function yourBusinessLogic() { try { await gunzipFile('待解压文件路径.gz', '解压后输出路径.txt'); // 此处写解压完成后的后续业务逻辑 } catch (err) { console.error('解压失败:', err); } }
同步阻塞方案(仅适合小文件,大文件会卡住主线程)
如果需要完全阻塞流程直到解压完成,可以直接使用zlib提供的同步API:
import { gunzipSync } from 'zlib'; import { readFileSync, writeFileSync, statSync } from 'fs'; function fileExists(filePath: string) { try { return statSync(filePath).isFile(); } catch (err) { return false; } } function gunzipFileSync(source: string, destination: string): void { if (!fileExists(source)) { throw new Error(`the source: ${source} does not exist`); } const compressedContent = readFileSync(source); const decompressedContent = gunzipSync(compressedContent); writeFileSync(destination, decompressedContent); }
调用时不需要异步等待,函数执行完成后自动走后续逻辑:
try { gunzipFileSync('待解压文件路径.gz', '解压后输出路径.txt'); // 此处写解压完成后的后续业务逻辑 } catch (err) { console.error('解压失败:', err); }
内容的提问来源于stack exchange,提问作者SarahJessica
相关产品推荐
相关产品推荐

