0

The actual Problem

The problem I am trying to solve is that a user may not provide enough information on a message (discord). To then get all of the necessary data the user is prompted to react to a bot message. There are 3 stages of that bot message, "InitialPrompt", "TimeoutWarning" and "TimeoutSuccess(TicketFailure)".

What I wanted the solution to be

With the way I've written my code there is no way to abort the timeout after it has been initialized. I thought that throwing an error would stop the execution of a function. I guess that doesn't happen because async calls get queued up instead of being ran line by line.

Is there a way to do this without adding a boolean and checking infront of each function call?

The solution that I could come up with

const interPtr = {interrupted : false};
interruptSignal(interPtr);

if(interPtr.interrupted) return;
console.log("...");
...

The actual code

JS Fiddle

(async () => {
  const sleep = async time => new Promise(resolve => setTimeout(resolve, time));

  const interruptSignal = () => new Promise(async (res, rej) => {
    console.log("interruptStarted")
    await sleep(2000);
    console.log("interruptRan");
    throw "Interrupted"
  });
  

  const timeOutHandler = async () => {
    interruptSignal();
    console.log("TimeoutStarted")
    await sleep(5000);
    console.log("TimeoutWarning")
    await sleep(5000);
    console.log("TimeoutSuccess->TicketFailure")
  };

  try {
    await timeOutHandler();
  } catch (e) {
    console.log(e);
  }
  
})()
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Twiggeh
  • 1,030
  • 1
  • 12
  • 24
  • You cannot achieve that. – Asutosh Aug 16 '20 at 14:42
  • 1
    [Never pass an `async function` as the executor to `new Promise`](https://stackoverflow.com/q/43036229/1048572)! You'd want just `async () => {` instead of `() => new Promise(async (res, rej) => {`. (But no, that doesn't solve your problem, the `interruptSignal();` promise is still not awaited and won't interrupt the execution of `timeoutHandler`). – Bergi Aug 16 '20 at 14:43
  • 1
    "*Is there a way to do this without adding a boolean and checking infront of each function call?*" - no, not really. Checking for an `isInterrupted` or `isCancelled` flag is still the way to go. – Bergi Aug 16 '20 at 14:47
  • @Bergi I see why I was using Promises in a wrong way, my bad. Thank you for pointing that out (this is actually the first time I tried to do something like that ). I was trying out more things => https://jsfiddle.net/Twiggeh99/4zojk2tn/7/, would you know why "TimeoutWarning" still runs, despite `lock` having failed already ? – Twiggeh Aug 16 '20 at 15:51
  • @Twiggeh Because you're still calling `func()` which logs the output, and only after that the `Promise.race` notices that the `lock` is rejected. I would recommend not to use a promise in `createLock` and `Promise.race` for the executing, but simple boolean flags like you had in mind originally. And actually you'll need to race the `sleep(5000)` with the `lock`, if that is what you want to get interrupted. – Bergi Aug 16 '20 at 15:57

0 Answers0