5

I need to get the value of a Javascript Promise object in a synchronous way.

I know how it works a Promise object in Javascript, and its advantages, and how to process the value with the then method, but there are use cases, specially with Node.js (but this could apply to browser engines also) where you need to return just the value, but you are calling an API that returns a Promise objects instead, and you can't change the signature of that API, or the consumer API.

In Java language for example, you have the get() method, that allows you wait if necessary for complete the action (blocks the execution), and then returns its result. Even you have a get(timeout,unit) with the maximum time to wait before launch an TimeoutException if the wait timed out.

The problem I have is something like this:

api1.setCallBackThatHasToReturnANoPromiseValue(
  function(p1, p2) {
    return api2.getPromisedValue(p1,p2)        // This returns a Promise
                                       .get()  // -> but something like this
                                               //    could get the value in a sync way
  }
);

Can someone tell me if I can resolve this with async programing?

And regardless of my specific problem that could be fixed with async code, there is a way to get the value of a Promise in a sync way (I know it will block the execution and all the performance issues, please avoid the "bla bla...").

Mariano Ruiz
  • 4,314
  • 2
  • 38
  • 34
  • 2
    I think you're confused about these concepts. Promises are necessary because the code *is* async. If it could be done synchronously, there would be no need for Promises to begin with. If this is in NodeJS, they do have synchronous versions of many methods, but if that's not available to you, then the answer is "no". –  May 13 '16 at 23:08
  • 1
    The promise is effectively in the asynchronous world. Once something is triggered asynchronously there is no way to make it synchronous again. – Edwin Dalorzo May 13 '16 at 23:10
  • @squint as I said, I'm dealing with two different API, so I cannot change the fact that one uses promise and the other doesn't. Can you see the example code and tell me how to resolve that? – Mariano Ruiz May 14 '16 at 03:09
  • 2
    @edwin-dalorzo: It's not the same says "there is no way..." than "there is no way in *Javascript*", the requirement is very simple an can be done in many platforms, like the Java example that I provided. You are telling me that in Javascript, or maybe more specifically with standard Promise object cannot be done? – Mariano Ruiz May 14 '16 at 03:12
  • @amit: It's similar but not duplicated, may question is about Promise object specifically, not any other async methods like the jQuery or other APIs use, even I provided a code example with a different problem that in the other question, so I think that there is no need to close or modify the question. If you agree, Can you unmark the question as duplicate? – Mariano Ruiz May 14 '16 at 03:14
  • @Mrdev: I already told you. You can't resolve it in a synchronous way. When async code exists, you need to use async patterns, of which Promises is one. –  May 14 '16 at 14:25

2 Answers2

4

I need to get the value of a Javascript Promise object in a synchronous way.

You can't. If an API returns a promise that's because the operation is asynchronous. At the time your function returns, the value is simply not known yet and Javascript does not provide any mechanism to wait for the result before returning.

Instead, you have to design for an asynchronous response and your caller has to code for an asynchronous response. Since you're already using promises, that means your caller needs to use a .then() handler on the promise to get access to the asynchronous result and that .then() handler will get called some time in the future, long after the API call has already returned.

It's important to understand that Javascript in browsers and node.js is fundamentally different than Java. These Javascript environments are single threaded and event driven. That means you can't block and wait for something to happen before returning. Instead you have to return and let the event queue run so your async result can eventually be processed and trigger a callback. If you did try to block and wait for a result (some people trying making busy loops that just loop for a couple seconds to simulate a sleep() call one might use in another language), you'd have a deadlock because the result could not be processed until you stopped blocking, but you wouldn't stop blocking until the result was ready. You'd just end up with an infinite loop.

So, instead you have to learn to program for async responses in Javascript, either via a plain callback or using promises and their associated .then() handlers. And, all consumers of that async result have to know it's async and program accordingly.


In addition, a promise is a representation of a future value. You only get access to it with a .then() handler that will be called when (sometime in the future) the value is ready or an error occurs. There is no synchronous way to get a value from a promise.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • "You can't block and wait" - you don't have to block; the scheduler just has to move on to something else in the queue and resume this function later. This is common in other languages, and isn't that exactly what `await` does anyway? The OP's question is essentially "if `await` can do this, then why don't promises have a .`suspend_till_resolved` method? – EML Aug 21 '23 at 09:59
  • @EML - That isn't how `await` works. You can ask the designers of Javascript why they did it this way, but `await` only suspends execution of the containing function and then causes it to immediately return a promise in the `pending` state. Execution after the function call continues where the function returns the promise and execution continues in that sequence of code until that code returns from whatever event started this sequence of code in the first place. Only at that point will the interpreter go get the next event from the queue and run it. – jfriend00 Aug 21 '23 at 20:40
1

If you can use ES2016(ES7) features (via Babeljs or a library), you can use async-await.

Using async-await you define a function as having asynchronous code and then use the await keyword to wait for a response from an async function. The async function needs to return a promise. Async-await lets you write async code as if it were synchronous.

kevintechie
  • 1,441
  • 1
  • 13
  • 15
  • I cannot use ES7 now, but looks awesome, I hope these features will available soon in next stable versions of Node.js. – Mariano Ruiz May 14 '16 at 03:32
  • 5
    @Mrdev: Indeed this is a nice feature, but just so you're clear, even if this feature was available today, it wouldn't help your current situation. As @ kevintechie wrote, *"The async function needs to return a promise."*. This is just syntax sugar, and doesn't add anything to what you can already do. It just cleans it up. –  May 14 '16 at 15:02