asynchronous – How to wait for a JavaScript Promise to resolve before resuming function?

asynchronous – How to wait for a JavaScript Promise to resolve before resuming function?

Im wondering if there is any way to get a value from a Promise or
wait (block/sleep) until it has resolved, similar to .NETs
IAsyncResult.WaitHandle.WaitOne(). I know JavaScript is
single-threaded, but Im hoping that doesnt mean that a function
cant yield.

The current generation of Javascript in browsers does not have a wait() or sleep() that allows other things to run. So, you simply cant do what youre asking. Instead, it has async operations that will do their thing and then call you when theyre done (as youve been using promises for).

Part of this is because of Javascripts single threadedness. If the single thread is spinning, then no other Javascript can execute until that spinning thread is done. ES6 introduces yield and generators which will allow some cooperative tricks like that, but were quite a ways from being able to use those in a wide swatch of installed browsers (they can be used in some server-side development where you control the JS engine that is being used).


Careful management of promise-based code can control the order of execution for many async operations.

Im not sure I understand exactly what order youre trying to achieve in your code, but you could do something like this using your existing kickOff() function, and then attaching a .then() handler to it after calling it:

function kickOff() {
  return new Promise(function(resolve, reject) {
    $(#output).append(start);
    
    setTimeout(function() {
      resolve();
    }, 1000);
  }).then(function() {
    $(#output).append( middle);
    return  end;
  });
}

kickOff().then(function(result) {
    // use the result here
    $(#output).append(result);
});

This will return output in a guaranteed order – like this:

start
middle
end

Update in 2018 (three years after this answer was written):

If you either transpile your code or run your code in an environment that supports ES7 features such as async and await, you can now use await to make your code appear to wait for the result of a promise. It is still programming with promises. It does still not block all of Javascript, but it does allow you to write sequential operations in a friendlier syntax.

Instead of the ES6 way of doing things:

someFunc().then(someFunc2).then(result => {
    // process result here
}).catch(err => {
    // process error here
});

You can do this:

// returns a promise
async function wrapperFunc() {
    try {
        let r1 = await someFunc();
        let r2 = await someFunc2(r1);
        // now process r2
        return someValue;     // this will be the resolved value of the returned promise
    } catch(e) {
        console.log(e);
        throw e;      // let caller know the promise was rejected with this reason
    }
}

wrapperFunc().then(result => {
    // got final result
}).catch(err => {
    // got error
});

async functions return a promise as soon as the first await is hit inside their function body so to the caller an async function is still non-blocking and the caller must still deal with a returned promise and get the result from that promise. But, inside the async function, you can write more sequential-like code using await on promises. Keep in mind that await only does something useful if you await a promise so in order to use async/await, your asynchronous operations must all be promise-based.

If using ES2016 you can use async and await and do something like:

(async () => {
  const data = await fetch(url)
  myFunc(data)
}())

If using ES2015 you can use Generators. If you dont like the syntax you can abstract it away using an async utility function as explained here.

If using ES5 youll probably want a library like Bluebird to give you more control.

Finally, if your runtime supports ES2015 already execution order may be preserved with parallelism using Fetch Injection.

asynchronous – How to wait for a JavaScript Promise to resolve before resuming function?

Another option is to use Promise.all to wait for an array of promises to resolve and then act on those.

Code below shows how to wait for all the promises to resolve and then deal with the results once they are all ready (as that seemed to be the objective of the question); Also for illustrative purposes, it shows output during execution (end finishes before middle).

function append_output(suffix, value) {
  $(#output_+suffix).append(value)
}

function kickOff() {
  let start = new Promise((resolve, reject) => {
    append_output(now, start)
    resolve(start)
  })
  let middle = new Promise((resolve, reject) => {
    setTimeout(() => {
      append_output(now,  middle)
      resolve( middle)
    }, 1000)
  })
  let end = new Promise((resolve, reject) => {
    append_output(now,  end)
    resolve( end)
  })

  Promise.all([start, middle, end]).then(results => {
    results.forEach(
      result => append_output(later, result))
  })
}

kickOff()
<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script>
Updated during execution: <div id=output_now></div>
Updated after all have completed: <div id=output_later></div>

Leave a Reply

Your email address will not be published.