0

I have async code that I'd like to stop running when I reject.

Note:

let ingestPromises = event.Records.map(async (record, i) => {
    let camera = JSON.parse(record.body)
    return new Promise(async (resolve, reject) => {

        let imageBuffer;
        try {
            imageBuffer = await retrieveImageFromURI(camera.ing_uri)
            console.log(`Record #${i} Successful Ingestion from URI`);
        } catch (err) {
            console.log("Going to reject");
            reject({ 'Task': `Attempting to pull image from camera (${camera.camName}`})
            console.log("Rejected");
        }

        console.log("Going to save file now...");
   //    ... blah blah more code ...
})}

let settledPromises = await Promise.allSettled(ingestPromises)
console.log('All promises settled :>> ', settledPromises);

When I run this against an invalid uri, the retrieveImageFromURI function throws a timeout error as expected. This skips the "Record X successful ingestion..." message and jumps to the catch block as expected. However, then things go unexpectedly.

Output from the above code, when retrieveImageFromURI throws an error looks like this:

Going to reject
Rejected
Going to save file now...
All promises settled :>>  [ {
    status: 'rejected',
    reason: {
      Task: 'Attempting to pull image from camera (TEST Camera)'
    }
}]

It is my expectation that the reject would stop any further processing within that promise (much like a return would) and I would NOT see 'Rejected' nor 'Going to save file now...' console.logs...

What am I misunderstanding here?

lowcrawler
  • 6,777
  • 9
  • 37
  • 79
  • A note about using async Promise executor ... don't, just don't i.e. `new Promise(async (resolve, reject) => {` if there's something to `await` inside there, there's almost never a reason to construct a new Promise - here's how your code could be written better https://pastebin.com/VRxNYCUr – Bravo Mar 05 '22 at 04:31
  • Depends what you mean by "to stop running". Do you want to inhibit further iterations of `.map()`? – Roamer-1888 Mar 05 '22 at 14:16

3 Answers3

1

Add return to stop execution, since reject is just a function, it can't make the function stop executing.

try {
  // ...
} catch (err) {
  console.log("Going to reject");
  reject({
    'Task': `Attempting to pull image from camera (${camera.camName}`
  });
  console.log("Rejected");
  return;
}

If you have a finally clause, you will need to add a variable to keep track:

Note: This isn't helpful here, since finally is supposed to execute regardless of whether catch occurred, but if you have extra checks inside of catch, the return will go into the finally so an extra variable is needed.

let shouldReturn = false;
try {
  // ...
} catch (err) {
  console.log("Going to reject");
  reject({
    'Task': `Attempting to pull image from camera (${camera.camName}`
  });
  console.log("Rejected");
  let shouldReturn = true;
  return;
} finally {
  if (shouldReturn) return;
}
Samathingamajig
  • 11,839
  • 3
  • 12
  • 34
1

There's nothing special about invoking reject. It's just a function. If you want to bail on further processing, your function should return.

try {
  imageBuffer = await retrieveImageFromURI(camera.ing_uri)
  console.log(`Record #${i} Successful Ingestion from URI`);
} catch (err) {
  console.log("Going to reject");
  reject({ 'Task': `Attempting to pull image from camera (${camera.camName}`})
  console.log("Rejected");
  return;
}
ray
  • 26,557
  • 5
  • 28
  • 27
0

Do I need to return after early resolve/reject? indicates that the first reject (or a resolve) will define the fullfilled value of a Promise, but they actively do NOT stop execution and a return is needed.

lowcrawler
  • 6,777
  • 9
  • 37
  • 79