0

I have a function that uses spawn and calls ffmpeg to trim a file, which returns a Promise. I need to trim an audio file into multiple parts, so I iterate with a for loop which launches the trimming function, I only need the trimming process to complete (which generates the trimmed file) in the for loop (so I don't need to use await) but still need to make sure the trimming function did not return error.

for (let i = 0; i < myArray.length; i++) {
        trim().catch(console.error); //<--- Trim asynchronously
        linkedList.insertAtEnd(i); 
}

My problem is what is a good way to run the for loop trimming the audio asynchronously?

Edit: I don't want the trim() function to complete to iterate the next element in the array.

Edit: The difference between my question and this one is I don't want the for loop to wait for the trim() function in order to go on to the next element in the array.

hkisthebest
  • 101
  • 1
  • 9
  • 5
    Example code and desired results are encouraged. – Ryan Wilson Dec 10 '19 at 17:47
  • 1
    Does this answer your question? [Callback after all asynchronous forEach callbacks are completed](https://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-callbacks-are-completed) – Klaycon Dec 10 '19 at 17:54
  • 1
    @RyanWilson Edited, sorry for the inconvenience. – hkisthebest Dec 10 '19 at 18:00
  • `trim()` takes no parameters, so how does it know what it is working on? Also, since there is no `await`, `trim()` likely does not complete "in the for loop" but after. On top of that, you *code* has no way to know if there was an error, as you only output that to the console. – crashmstr Dec 10 '19 at 18:02
  • @Klaycon I think the difference is that I don't need to wait for the async function to finish in order to iterate the next element in the array. – hkisthebest Dec 10 '19 at 18:02
  • @crashmstr I simplified the code a lot, as you mentioned `trim()` doesn't complete "in the for loop" but after. That is what I am trying to achieve. – hkisthebest Dec 10 '19 at 18:04
  • Show us your `trim()` method. – TGrif Dec 10 '19 at 18:11
  • To know that there were no errors, you to 1. save success or failure for each call and 2. check those values after all are completed (i.e. `Promise.all`). – crashmstr Dec 10 '19 at 18:31
  • @TGrif I don't think it is relevant in this case, since it only returns string res("the function completed") and rej(new Error("something wrong")). – hkisthebest Dec 10 '19 at 18:32
  • @crashmstr And in order to store the promise that it returns, I need to wait for the result before going to the next element, am I right? So how could I achieve what I mentioned in the post? – hkisthebest Dec 10 '19 at 18:39
  • @hkisthebest The second solution under "Using ES6 Promises" in the answer to the linked question contains an example of using `Promise.all()` to run all promises in the loop alongside each other. It will resolve when all subtasks have resolved -or- reject as soon as one subtask rejects. You can `.catch()` the `Promise.all()` to handle the latter case – Klaycon Dec 10 '19 at 19:10

1 Answers1

1

To know if there is any error, you need to deal with it at some point, and to do that, you need to know when they are all done, even if you do not want to wait on each before the next iteration of the loop.

To do this, either store each promise into an array (or use .map). You can then Promise.all to trigger code when each call of trim has completed.

I've added trim and myArray definitions and commented out the insertAtEnd for a "run-able" example (though having the linked list insert not being dependent on the trim makes little sense, nor does trim not taking any variants from the loop itself).

function trim() {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(), 5)
  });
}

let myArray = [1, 2, 3, 4];
let results = [];
for (let i = 0; i < myArray.length; i++) {
  results.push(trim().then(() => true).catch(() => false))
  console.log(`iteration ${i} finished`);
  //linkedList.insertAtEnd(i); 
}

Promise.all(results).then((r) => {
  console.log(`trim() results: ${r}`);
  if (r.every((x) => x)) {
    console.log('success');
  } else {
    console.log('an error occurred');
  }
});
crashmstr
  • 28,043
  • 9
  • 61
  • 79