0

I'm kind of stuck trying to do some async in NodeJS for the first time. I read a bit about Promises and async/await but still confused what would be the best to do in my case where one async function is inside the other.

function startTheater(sourceAudioFile) {
  decodeSoundFile(sourceAudioFile).then((result) => {
    setLight(); //this has to run only run after decodeSoundFile is complete
  });
}

function decodeSoundFile(soundfile) {
  return new Promise(function(resolve, reject) {
    fs.readFile(soundfile, function(err, buf) {
      if (err) throw err
      context.decodeAudioData(buf, function(audioBuffer) {
      playSound();
        findPeaks(pcmdata, samplerate); <<<<<< this function itself has has to finish before decodeSoundFile returns <<<<<<
     if (lightPlant.length != 0) {
        resolve("light plan populated");
      } else {
        reject(new Error("broke promise. unable to populate"));
      }
      }, function(err) {
        throw err
      })
    })
  });
}

The following function takes a while to complete but the above decodeSoundFile returns before it's completion. How do I prevent that when decodeSoundFile itself is a promise?

function findPeaks(pcmdata, samplerate) {
  var interval = 0.5 * 1000;
  var step = samplerate * (interval / 1000);

  //loop through sound in time with sample rate
  var samplesound = setInterval(function() {
    if (index >= pcmdata.length) {
      clearInterval(samplesound);
      console.log("finished sampling sound"); <<this is where decodeSoundFile is good to return after findPeaks execution. 
    }

    for (var i = index; i < index + step; i++) {
      max = pcmdata[i] > max ? pcmdata[i].toFixed(1) : max;
    }
    prevmax = max;
    max = 0;
    index += step;
  }, interval, pcmdata);
}

How do I do this chain this execution in the right way?

  • here's some things about the code you posted that are odd. in decodeSoundFile: 1. what is `audioBuffer` - you never use that. 2. what is `lightPlant`, `pcmdata`, `samplerate` - they come from nowhere. - in findPeaks: 1. what is `pevmax` - it comes from nowhere – Bravo Aug 22 '21 at 03:04
  • Sorry, I just wanted to keep the question short without all of the audio complexities that I'm dealing with. That's where those orphan variables are from. – user2607717 Aug 22 '21 at 03:11
  • No need to put them in, just found it odd :p as long as you know what they are, it doesn't effect the answer – Bravo Aug 22 '21 at 03:12

1 Answers1

0
import { readFile } from 'fs/promises';

function startTheater(sourceAudioFile) {
    decodeSoundFile(sourceAudioFile).then((result) => {
        setLight(); //this has to run only run after decodeSoundFile is complete
    });
}

function decodeSoundFile(soundfile) {
    return fs.readFile(soundfile)
    .then(buf => new Promise((resolve, reject) => context.decodeAudioData(buf, resolve, reject)))
    .then(audioBuffer => {
        playSound();
        return findPeaks(pcmdata, samplerate);
    })
    .then(() => {
        if (lightPlant.length != 0) {
            return "light plan populated";
        } else {
            return Promise.reject(new Error("broke promise. unable to populate"));
        }        
    });
}

function findPeaks(pcmdata, samplerate) {
    return new Promise(function (resolve, reject) {
        var interval = 0.5 * 1000;
        var step = samplerate * (interval / 1000);

        //loop through sound in time with sample rate
        var samplesound = setInterval(function () {
            if (index >= pcmdata.length) {
                clearInterval(samplesound);
                console.log("finished sampling sound");
                resolve();
            }
            for (var i = index; i < index + step; i++) {
                max = pcmdata[i] > max ? pcmdata[i].toFixed(1) : max;
            }
            prevmax = max;
            max = 0;
            index += step;
        }, interval, pcmdata);
    });
}

using async/await in decodeSoundFile as requested (and startTheater)

async function startTheater(sourceAudioFile) {
    const result = await decodeSoundFile(sourceAudioFile);
    setLight();
}

async function decodeSoundFile(soundfile) {
    const buf = await fs.readFile(soundfile);
    const audioBuffer = await new Promise((resolve, reject) => context.decodeAudioData(buf, resolve, reject));
    await findPeaks(pcmdata, samplerate);
    if (lightPlant.length != 0) {
        return "light plan populated";
    } else {
        return throw new Error("broke promise. unable to populate");
    }        
}
Bravo
  • 6,022
  • 1
  • 10
  • 15
  • Just editted my question showing how I am resolving promise inside `decodeSoundFile()`. If that's the case would findPeaks still resolve okay when `findPeaks` promise is nested inside decodeSoundFile? For some reason (after reading another post), I thought only the first `resolve` would work when a promise is nested inside another – user2607717 Aug 22 '21 at 02:58
  • that's how chaining promises works @user2607717 – Bravo Aug 22 '21 at 03:04
  • Can you change your edits to the one with `await`? That works for me in terms of chaining and getting what I want. I was just hesitant to use a promise inside a promise thinking there might be a more elegant/clever way but I guess I was just overthinking. Thank you for your help – user2607717 Aug 22 '21 at 03:12
  • why do you need `await` - I removed async/await because you aren't using it, didn't know if you knew how - but OK – Bravo Aug 22 '21 at 03:13
  • @user2607717 - added async/await version of `decodeSoundFile` – Bravo Aug 22 '21 at 03:17
  • Thanks. Btw, in your first solution, I'm not sure why `decodeSoundFile` is returning `findPeaks`? If `findPeaks` is a now a promise as well, then I could write the resolve for `decodeSoundFile` in the function as `findPeaks(pcmdata, samplerate).then( () => {resolve() });` Would this also be okay to do? – user2607717 Aug 22 '21 at 03:20
  • @user2607717 ... `.then` **always** returns a Promise - returning a Promise inside `.then` means the Promise `.then` returns "takes on" the Promise you return - plus, you can't `resolve()` when there's no function `resolve` anymore - perhaps reading some [docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) will help you understand Promises a bit better – Bravo Aug 22 '21 at 03:25