1

Let's say I have three async functions set as below:

const stepOne = async () => { setTimeout(function() {
  console.log("step 1")
}, 3000)  }

const stepTwo = async () => { throw new Error("Error at step two") }

const stepThree = async () => { console.log("step 3") }

How will I execute all these functions sequentially and break the promise chain at stepTwo not allowing stepThree function to run ever?

So,

normal sequence is like this: stepOne --> stepTwo --> stepThree

sequence with error thrown at stepTwo: stepOne --> stepTwo

The error thrown at stepTwo needs to get caught at end catch block.

UPDATE #1: Missed a crucial element of the question. await cannot be used as these three functions need to be called within a function which is not async.

example:

const testFunc = () => { 
  
  resolve three promises 
  sequentially, break the promise chain when error is thrown 
  and ultimately, catch errors here
   
  }
san
  • 31
  • 8
  • 1
    Generally: `try { await stepOne(); await stepTwo(); await stepThree(): } catch ...`. However, your `stepOne` doesn't wait for the `setTimeout` to resolve. There's no way to await that `setTimeout` without changing the implementation of `stepOne`… – deceze Sep 18 '20 at 10:19
  • @deceze : My apologies! await is not an option. updated my question. – san Sep 18 '20 at 13:01
  • If you can't use `await`, then you cannot catch the error by `try..catch`. You need to chain them with the good old `then.then.catch`. – deceze Sep 18 '20 at 13:03
  • @deceze : yes, understand. however, I wanted to notify that error need to be caught. Shouldn't have used try.. catch block if it was misleading. I removed it from the question. – san Sep 18 '20 at 13:13
  • 1
    So: `stepOne().then(stepTwo).then(stepThree).catch(e => console.error(e))`… – deceze Sep 18 '20 at 13:15

3 Answers3

2

Your code would work if you would resolve the promise from stepOne because setTimeout just adds the function to the stack and is not waiting for it to resolve.

If you would return a Promise from stepOne and resolve it after the console.log then the try catch will wait for stepOne and catch the error on stepTwo

Here is your code example

const stepOne = async () => {
    return new Promise((resolve, reject) => {
        setTimeout(function() {
            console.log("step 1")
            resolve(true);
        }, 3000)
    });
}

const stepTwo = async () => { throw new Error("Error at step two") }

const stepThree = async () => {
    return new Promise((resolve, reject) => {
        setTimeout(function() {
            console.log("step 3")
            resolve(true);
        }, 3000)
    });
}


(() => {
    stepOne()
        .then(stepTwo)
        .then(stepThree)
        .catch(error => {
            console.log(error);
        })  
})();

Now the console.log looks like this

step 1
Error: Error at step two
    at stepTwo (/home/user/develop/test/stackoverflow.js:10:38)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
BraveButter
  • 1,408
  • 9
  • 22
1

Please try the below code. You need to wait for each call (stepOne, stepTwo and stepThree) so that when there is any exception, the next call is not made.

try {
    await stepOne();
    await stepTwo();
    await stepThree()
} catch (error) {
    console.log(error);
}
Kiran
  • 54
  • 3
1

If your steps are functions that return a Promise, you could create a wrapper function that will call each step in sequence and abort if a step fails, logging details of which step failed.

In this example, each step fails with a 1 in 5 chance.

// Make a step proc, that throws 1 time in 5
function createStep(index) {
    let error = (Math.random() < 0.2) ? new Error(`Step ${index+1} error`) : null ;
    return () => new Promise((resolve, reject) => setTimeout(error ? reject(error): resolve(`Step ${index+1} outcome`), 500));
}

async function runSteps(steps) {
   
   for(stepIndex = 0; stepIndex < steps.length; stepIndex++) {
       try {
         console.log(`Running step #${stepIndex+1}...`);
         let result = await steps[stepIndex]();
         console.log(`Step result:`, result);
       } catch (e) { 
         console.error(`An error occurred at step #${stepIndex+1}:`, e.message);
         break;
       }
       if (stepIndex === (steps.length -1) ) {
          console.log("All steps completed successfully");
       }
   }
}

let steps = Array.from( { length: 3 }, (v,k) => createStep(k));
runSteps(steps);
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40