0

I'm struggling with an event handler in javascript, I'm trying to make things respond correctly with async / await.

The issue in the code below is with the file.on event-- I'm struggling to promisify it correctly. Currently the checkSomething method returns before the file.on handler is finished, and so returnValue is always false.

I could use some advice and best practices.

What's a good way to go ensure returnValue is checked / set in the handler before the value is returned? I've tried putting the await keyword in front of the event handler, and in its callback function but that didn't work, and I'm basically scruffing along at this point and could use some tips. Thanks.

const axios = require('axios')
const fs = require('fs')

/*....*/

let isItChecked = await checkSomething()

async function checkSomething() {
    let returnValue = false
    const response = await axios.get('https://someUrl.com', {
        responseType: 'stream'
    })

    const file = fs.createWriteStream('./localFile.txt')

    response.data.pipe(file)

    file.on('finish' () => {
        performATask().then((result) => {
            if (result == 'good') {
                returnValue = true  //need to make sure this is evaluated before returning
            }
        })
    })

    return returnValue
}
larryq
  • 15,713
  • 38
  • 121
  • 190

2 Answers2

3

Since the event is only used as a signal for processing to continue, you can promisify and await its receipt before continuing with in-line style code. This also means that result need not be declared in outer scope of a nested fumction (which didn't work anyway due to being set asynchronously):

async function checkSomething() {
    const response = await axios.get('https://someUrl.com', {
        responseType: 'stream'
    });

    const file = fs.createWriteStream('./localFile.txt');
    response.data.pipe(file);
    await new Promise( resolve=> file.on(`finish`, resolve)); // wait here

    const result = await  performATask();
    return result == 'good`;
}
traktor
  • 17,588
  • 4
  • 32
  • 53
1

You're close, you just have to return a promise, which resolves after the execution reaches your desired point (where you have the comment).

Other things to keep in mind:

  • Ensure you only use await from within async functions
  • Use === instead of ==
  • End statements with ;s
const axios = require('axios');
const fs = require('fs');

/*....*/

let isItChecked = await checkSomething();

async function checkSomething() {
  const response = await axios.get('https://someUrl.com', {responseType: 'stream'});

  const file = fs.createWriteStream('./localFile.txt');

  response.data.pipe(file);

  return new Promise(resolve =>
      file.on('finish', () =>
          performATask().then(result => resolve(result === 'good'))));
}

junvar
  • 11,151
  • 2
  • 30
  • 46
  • This is for my own edification, I noticed that he/she was using await outside of their async function as well. Should the await that's being used in front of checkSomething() for the isItChecked variable be removed? – paoiherpoais Nov 06 '19 at 22:48
  • Depends on the omitted code. Perhaps that line is actually inside an `async` function. Otherwise, yes, using `await` is illegal and `isItChecked` could instead store the return promise directly. – junvar Nov 06 '19 at 22:49
  • https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it – Jonas Wilms Nov 06 '19 at 22:56
  • @JonasWilms yes, but the result is within the callback of an event handler. `file.on()` does not return a promise. – Patrick Roberts Nov 06 '19 at 22:59
  • @junvar Good point. I was assuming this was a standalone function being returned within a larger async function. Thanks for the feedback. – paoiherpoais Nov 06 '19 at 23:03
  • @paoiherpoais yes, the line in question is indeed inside an async function, just omitted it for space. And your suggestion worked great junvar, my sincere thanks. – larryq Nov 06 '19 at 23:03
  • @larryq Ah! Okay that explains it. Thanks. – paoiherpoais Nov 06 '19 at 23:03
  • @patrick but `performATask` does. The other answer does it correctly. – Jonas Wilms Nov 07 '19 at 01:29