How to block for a javascript promise and return the resolved result?

Chris Owens picture Chris Owens · Apr 4, 2015 · Viewed 44.7k times · Source

I am obviously misunderstanding something about either the way js promises are resolved or about the semantics of "return."

I am being called by a function that expects me to be synchronous - to return a value. Calculating that value requires some asynchronous code (specifically, the ForEach method on a dstore Collection

What I'm trying to accomplish is approximately this, but this does not work in that the function mySynchronousFunction has no return value.

function mySynchronousFunction() {
   var accumulator = {};
   var myPromise = doAsynchronousThingThatSideEffectsAccumulator();
   // Now my caller is expecting the value of accumulator.
   myPromise.then(function() {return accumulator;})
}

I understand that JS has to allow for single-threaded implementations, so that it's not cool to block, but there must be some pattern for gluing asynchronous to synchronous code, that I've just missed.

Answer

jfriend00 picture jfriend00 · Apr 4, 2015

You cannot make a synchronous result out of an asynchronous operation in Javascript. You just cannot do it. If any part of your operation is async, the entire result must be async and you must either use a callback, a promise or some other such mechanism to communicate when the operation is done and the result is ready.

If your async operation already returns a promise (which it looks like), then you should just return that from the wrapper function:

function myWrapperFunction() {
   var accumulator = {};
   var myPromise = doAsynchronousThingThatSideEffectsAccumulator(accumulator);
   // Now my caller is expecting the value of accumulator.
   return myPromise.then(function(result) {
       // operate on the accumulator object using the async result
       return accumulator;
   })
}

myWrapperFunction.then(function(accumulator) {
   // write your code here that uses the accumulator result
});

You may also want to note that a function that operates via side effects is rarely the best design pattern. You may as well pass in the input and have it return the output via the resolved promise and avoid side effects entirely.