Meteor method return after createWriteStream finished?

I would like to have a Meteor method return true after a NodeJS script with createWriteStream has finished. However, currently it returns as soon as the createWriteStream starts. How can I get it to wait?

Here’s the code I have currently:

const fs   = require( 'fs' );
const path = require( 'path' );

Meteor.methods({
  importCSVServer( doc ) {
    const urlObj        = doc.importURL;

    try {
      let thisKey     = urlObj.key.slice(1),
          getS3params = {
                            Bucket: '<bucket_name>',
                            Key: thisKey
                          },
          // Build a path string to the local CSV
          csvFile     = importDir + urlObj.name,
          // Create a write stream for data to land when coming from S3
          writeFile   = fs.createWriteStream( csvFile ),
          // Stream data from the CSV on S3 and pipe it to a new CSV on the server
          getFile     = S3.aws.getObject( getS3params ).createReadStream().pipe( writeFile );

      // Watch for events on the write stream. When finished writing from S3, start processing
      writeFile.
        on( 'error', ( error ) => {
          console.warn( 'writeFile error:' );
          console.warn( error );
        }).
        on( 'finish', Meteor.bindEnvironment( ( error, response ) => {
          Baby.parseFiles( csvFile, {
            header: true,
            step: ( results, parser ) => {
              <process csv row here>
            }, // End step function
            complete: ( results, file ) => {
              console.log( 'import finished' + ' at ' + moment().format() );

              let deleteFile = fs.unlinkSync( csvFile );

              return 'completed';
            }
          }); // end Baby.parseFiles
        })); // end on.Finish
    } catch ( error ) {
      console.warn('import error' );
      console.warn( error );
      throw new Meteor.Error( 500, 'Import failed.' );
    }
  }
});

I have tried moving the writeStream workflow to a separate function and have also looked at Meteor.wrapAsync and Futures, but writeStream always seems to destroy the order.

Appreciate any suggestions you may have.

Because meteor methods run synchronously. You have to ‘halt’ the return value until your result comes back as it were. This is a package that helps with that: https://atmospherejs.com/meteorhacks/async

In this case you could use

var asyncReturn = Async.runSync(function(done){
    ..... // All your async code in here
    .on('finish', (error, response) => {
        done(null, 'completed');
    });
});

return asyncReturn .result;

If you’re interested just read up on fibers, but this should help.

1 Like

Thanks @nlammertyn! That helped.