Solution 1 :

When you call this terminate() which is this:

function terminate() {
  setTimeout(() => console.log("Edning"), 1)
}

The setTimeout() pushes it’s callback to a future cycle of the event loop and EVERYTHING else in the current cycle of the event loop runs before it. Only when the current chain of code has finished and control has returned back to the event loop will the setTimeout() get a chance to run its callback.

So, here’s the sequence of what happens in your code:

  1. call() is executed.
  2. myprom() is executed. That resolves its promise immediately so it will schedule it’s .then() handlers to run as soon as control returns back to the event loop.
  3. .then() and .catch() run. All they do at this point is register some callbacks to be called later when the promise is ready to execute them.
  4. Your async function returns and control goes back to the event loop.
  5. The already resolved promise is first in line in the event loop so it gets control and executes it’s .then() handler.
  6. myfunc(1) runs and that outputs Starting in 1
  7. console.log(result) runs and that outputs I Promise to end without showing next line
  8. terminate() runs and that sets a timer for 1ms from now. That function returns and the timer is schedule to run on a future tick of the event loop when 1ms has passed.
  9. dummy(1) is called and that outputs I am not supposed to print anything.
  10. terminate() is called again and that again schedules another timer to run in 1ms on a future tick of the event loop.
  11. The await processes the promise and resolves the promise that the async function call() returns. The await does nothing useful here and there’s nothing listening for the promise that call() returns either.
  12. Control is returned back to the event loop.
  13. The first timer you set with the first call to terminate() gets to run and it outputs. That returns control back to the event loop.
  14. The second timer you set with the second call to terminate() gets to run and it puts. That returns control back to the event loop and everything associated with this code is done.

In general. how to stop js execution abruptly inside .then object?

If what you’re asking is how you skip the other functions you call all in a row, then you would typically use conditionals to branch of return early out of the .then() callback. For example, you could do this:

async function call() {
  await myprom("to end without showing next line")
    .then(result => {
      myfunc(1)                       // Call # 1
      console.log(result)             // Call # 2
      if (result === "I Promise to end without showing next line") {
          // skip the rest of the code in this callback
          return;
      }
      terminate()                     // Call # 3
      dummy(1)                        // Call # 4
      terminate()                     // Call # 5
    })
    .catch(err => {
      console.log(err)
    })
}

call()

Since you’re in a .then() handler, you could also so a throw someError and that would abruptly stop the .then() handler just like throwing any exception aborts the execution of the current function. Because this is in a .then() handler that exception will be immediately caught and will then execute the .catch() handler and pass it the exception you threw. This wouldn’t typically be used for a normal execution path because this more typically indicates some error condition. A normal execution path would more likely catch the condition locally and use branching or if/else logic or something like that to decide what code in the function executes next.


Note, if you’ve already started some timers, then to keep them from firing, you would have to save the timerID that setTimeout() returned and use clearTimeout() on that timerID to cancel the timer.

If you really want abrupt stopping to stop your whole process, then in node.js, you can also call process.exit().


It’s unclear why you thought the output from dummy(1) and the second call to terminate() would not show in the output? You called dummy(1). Nothing in the terminate() function causes Javascript to skip the rest of the code in the .then() handler. So, it continues and executes both dummy(1) and the second terminate() and thus you see the output from both.

Solution 2 :

Instead of calling terminate you could use return. That would solve your purpose.

Solution 3 :

The function terminate does not stop the execution of the function but instead schedules a function to run later with a timeout of at least 1 second. So, the function should instead be called delay. I have added a Promise based implementation of the same:

function delay(time = 1) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('Ending');
      resolve();
    }, time);
  })
}

A function returning a scalar value can be awaited. So, there is no need to wrap myProm using the Promise constructor. Assuming that myprom is a real async operation instead of a function returning a string, of course.

function myprom (value) {
  return `I Promise ${value}`;
}

When using async functions, the callback with .then and .catch is not necessary.

async function call() {
  try {
    const result = await myprom("to end without showing next line")
    console.log(result)
    myfunc(1)
  } catch (e) {
    console.error(e);
  }
}

The existing code snippet with the changes would look like this:

// scalar values can be resolved too
function myprom (value) {
  return `I Promise ${value}`;
}

function myfunc (value) {
  console.log("Starting in " + value)
}

function delay(time = 1) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('Ending');
      resolve();
    }, time);
  })
}


function dummy() {
  console.log("I am not supposed to print anything")
}

async function call() {
  try {
    const result = await myprom("to end without showing next line")
    console.log(result)
    myfunc(1)
    await delay();
    dummy(1);
    await delay();
  } catch (e) {
    console.error(e);
  }
  
  return undefined;
}

call();

However, as explained this will not stop the flow of execution:

  • myprom runs

  • result is printed

  • myFunc executes

  • after a delay of 1 second, a message of Ending prints (because the event loop is not blocked by many async operations)

  • dummy executes

  • after a delay of 1 second, a message of Ending prints

  • the function returns a Promise that resolves to a value of undefined.

Instead of using delay, we can use return when we need to terminate the execution of the function:

function myprom(value) {
  return `I Promise ${value}`;
}

function myfunc(value) {
  console.log("Starting in " + value)
}


async function call() {
  try {
    const result = await myprom("to end without showing next line")
    console.log(result)
    myfunc(1);
    return
  } catch (e) {
    console.error(e);
  }
}

call();

Problem :

I am trying to write logic in JS to stop function execution abruptly (without executing further) when in call sequence. Check below code. Why isn’t stopping after second call?

function myprom (value) {
  return new Promise (function (resolve, reject) {
    resolve("I Promise " + value)
  })
}

function myfunc (value) {
  console.log("Starting in " + value)
}

function terminate() {
  setTimeout(() => console.log("Edning"), 1)
}

function dummy() {
  console.log("I am not supposed to print anything")
}

async function call() {
  await myprom("to end without showing next line")
    .then(result => {
      myfunc(1)                       // Call # 1
      console.log(result)             // Call # 2
      terminate()                     // Call # 3
      dummy(1)                        // Call # 4
      terminate()                     // Call # 5
    })
    .catch(err => {
      console.log(err)
    })
}

call()

Below is the actual output of my code.

Starting in 1
I Promise to end without showing next line
I am not supposed to print anything
Ending
Ending

What is expected is,

Starting in 1
I Promise to end without showing next line
Ending

In general. how to stop js execution abruptly inside .then object?

Comments

Comment posted by Mike ‘Pomax’ Kamermans

It’s a good idea to run your code: I’m

Comment posted by Mike ‘Pomax’ Kamermans

Having said that:

Comment posted by charlietfl

One way is

Comment posted by Mulan

.then(myFunc).then(terminate).then(dummy)

Comment posted by Mike ‘Pomax’ Kamermans

Either add code to this answer, or make this a comment. As is, this is not an answer.

By