typescriptasync-awaitfsdata-stream

Await the Completion of a Readable Stream ES8 TypeScript, fs


My code isn't working because the file hasn't unzipped before the next line executes. This is my function for unzipping:

import { createGunzip } from 'zlib';
import { createReadStream, statSync, createWriteStream } from 'fs';

function fileExists(filePath: string) {
  try {
    return statSync(filePath).isFile();
  } catch (err) {
    return false;
  }
}

async function gunzipFile(source: string, destination: string): Promise<void> {
  if (!fileExists(source)) {
    console.error(`the source: ${source} does not exist`);
    return;
  }
  const src = createReadStream(source);
  const dest = createWriteStream(destination);
  await src.pipe(createGunzip())
    .pipe(dest)
    .on('error', (error) => {
      // error logging
    })
    .on('end', () => {
      return;
    });
}

How would I refactor this to get it to properly work asynchronously? Or non-async if it'll wait before completing. There are similar questions but they don't work for me, perhaps because this function returns void, not the data that has been streamed.


Solution

  • src.pipe not return a Promise then you can not wait on it. Let's convert it into a Promise:

    function gunzipFile(source: string, destination: string): Promise<void> {
      if (!fileExists(source)) {
        console.error(`the source: ${source} does not exist`);
        return;
      }
      const src = createReadStream(source);
      const dest = createWriteStream(destination);
    
      return new Promise((resolve, reject) => { // return Promise void
        src.pipe(createGunzip())
          .pipe(dest)
          .on('error', (error) => {
            // error logging
            // reject(error); // throw error to outside
          })
          .on('finish', () => {
            resolve(); // done
          });
      })
    }