5

Can you stop code outside of the async function using await? However, I don't want all code to stop. I want to control what code will run.

I think there might be a solution, something like this:

var isAsyncRunning = false;
var currentPromise;
async function asyncFunc(){
    isAsyncRunning = true;
    //Do some code here
    currentPromise = promise; //promise was defined inside the code
    await promise;
    promise.then(function(){
        isAsyncRunning = false;
    });
}
async function anotherFunction(){
    if(!isAsyncRunning){
        await currentPromise;
    }
    //Do some other code here
}

However, I have a lot of functions and don't want to apply this to every single function that I have.

Is there a better solution? If not, is there anything I can do to make this less time-consuming?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
MasterBob
  • 550
  • 1
  • 8
  • 19
  • What applying this to every single function accomplish? Some background or example might help. – jib Jan 05 '17 at 02:47
  • Not every single function. I said to *control* what it stops, not apply it to all of the functions. – MasterBob Jan 05 '17 at 03:27
  • 1
    you can't use `await` inside a function that isn't set as `async` - so `anotherFunction` is invalid – Jaromanda X Jan 05 '17 at 03:44
  • @JaromandaX Oh yes, forgot about that. Fixed! – MasterBob Jan 05 '17 at 03:46
  • What are you trying to achieve with this? If you want to run promises in sequence you can use `reduce` function in `bluebird` or if you prefer vanilla javascript use this approach: http://stackoverflow.com/a/36672042/177006 – bman Jan 05 '17 at 04:03
  • I don't want to run promises in sequence. I want to pause some code, but control which code is paused using `await`. – MasterBob Jan 05 '17 at 04:31
  • @MasterBob Forget `await` for a moment. What problem are you trying to solve, and what behavior do you expect? You can't arbitrarily "pause" or "stop" code in JS. JS doesn't have threads (web workers aside). – jib Jan 05 '17 at 05:34
  • @jib If almost everyone is not going to get what the question is about, here's an example: `prompt`. `prompt` stops all code _except_ for the user typing. I want to implement something like that, but I want to control which I stop and which I keep running, – MasterBob Jan 05 '17 at 23:13
  • @MasterBob: after your latest comment, I updated my answer with a new section. Hopefully that answer your question. – bman Jan 06 '17 at 06:02

1 Answers1

9

I think your understanding of Promises and async/await is not correct. When you make a function async, the await keyword before a promise make sure that code execution will pause until the promise fulfilled or rejected. Your code can be simplified:

var currentPromise;

async function asyncFunc(promise){
    // Do some code here
    return await promise;
}

function anotherFunction(){
    asyncFunc(currentPromise);
}

When we are calling return await promise, the execution engine waits in a non-blocking way until the promise fulfilled or rejected, and then it returns the output to the anotherFunction function.

Note: If you want to run promises in a sequence you can use reduce function in bluebird or this method, if you prefer vanilla javascript.

Pausing code execution

From your latest comment to the original question, I understand that you want to pause the execution of your program. First, you need to understand that stopping the Javascript execution in a blocking way is not possible. Javascript is a single-threaded programming language that uses event loop to handle concurrency. You can never stop the entire engine for an operation. Otherwise, the program will freeze. In a thread-based programming language, programmers use threads to implement concurrency.

In Javascript, however, you can pause the execution in a non-blocking way using async / await. For example:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function main() {
  await sleep(1500)
  console.log('Hello world with delay!')
}

main()

If I understand correctly, in your case you'd like to pause the execution based on a user input. You can implement any type of logic that you want. For example, the following program wait for the user to press the RETURN key:

function waitForUserInput(keyCode) {
  return new Promise(resolve => 
    document.addEventListener('keydown', (event) => {
      if (event.keyCode === keyCode) resolve()
    }
  )
}

async function main() {
  await waitForUserInput(13)
  console.log('Thank you for your submission!')
}

main()

In this example, the promise will not be resolved until the keyCode is pressed, and nothing will be logged into the console. Note, that waitForUserInput will not stop the Javascript engine. The engine will continue executing any other code and respond to UI events.

Community
  • 1
  • 1
bman
  • 5,016
  • 4
  • 36
  • 69
  • I know how it works, but I'm looking at your last line. "The engine will continue executing any other code and respond to UI events." I want to control if this code runs, or that code runs, or what. – MasterBob Jan 07 '17 at 01:34
  • 1
    @MasterBob You can do that by *await*, but you cannot pause the Javascript engine altogether. It is impossible! Please invest some time and read this article: https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop Also, take a look at this answer: http://stackoverflow.com/a/2734311/177006 – bman Jan 07 '17 at 01:38
  • I guess it is impossible then, and I will have to use my solution. This worries me, because now even regular functions will not work on browsers which do not support `async`/`await`. – MasterBob Jan 07 '17 at 01:47
  • 1
    @MasterBob: If you use `Babel` to transpile your code to ES5, all `async / await` will be converted to Promises and will work on all browsers. Check this out: http://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=latest%2Creact%2Cstage-2&experimental=false&loose=false&spec=false&code=function%20sleep(ms)%20%7B%0A%20%20return%20new%20Promise(resolve%20%3D%3E%20setTimeout(resolve%2C%20ms))%0A%7D%0A%0Aasync%20function%20main()%20%7B%0A%20%20await%20sleep(1500)%0A%20%20console.log('Hello%20world%20with%20delay!')%0A%7D&playground=true – bman Jan 07 '17 at 01:49
  • 1
    @MasterBob I am suspecting there is a structural problem with what you have in mind. Create a new question with the specific use case and ask for a structural answer. Pretty sure what you want to do is possible with Javascript if architectured correctly! – bman Jan 07 '17 at 01:51