42

Suppose some code does

// promise.js
let p = new Promise(() => { /* ... */ })
export default p

where Promise is an ES6 Promise. Suppose some other code has a reference only to p. How can that code tell if p is resolved or not?

// other.js
import p from './promise.js'
// console.log('p is resolved?', ______)

Is there something we can fill in the blank with that would show true or false depending on whether the promise is resolved or not?

trusktr
  • 44,284
  • 53
  • 191
  • 263

2 Answers2

42

The ES6 Promise constructor does not have a property that can tell you the state of the promise. You need to do something like this:

import p from './promise.js'
var isResolved = false;
p.then(function() {
  isResolved = true;
});

// ... At some point in the future.
console.log('p is resolved?', isResolved);

There is an internal property called PromiseState but you can't access it. Here is the spec.

Barney Szabolcs
  • 11,846
  • 12
  • 66
  • 91
nstoitsev
  • 740
  • 8
  • 7
  • 8
    This will always return false. Put console.log inside 'then' import p from './promise.js' var isResolved = false; p.then(function() { isResolved = true; console.log('p is resolved?', isResolved); }); – Aman Gupta Mar 01 '16 at 06:51
  • 4
    Help me to correct myself here. Why do you think this will always return false? – nstoitsev Mar 01 '16 at 06:52
  • 2
    because javascript is asynchronous and will execute console.log even before promise is resolved and at that time isResolved has 'false' value – Aman Gupta Mar 01 '16 at 06:54
  • 5
    Yes, you are right. But I expect there is some code execution between the moment the `then` handler is defined and the moment when `console.log` will be called. I guess that the author of the question want to be able to always tell whether the promise is completed. At any point in time isResolved will be false if the promise is not resolved. Right? – nstoitsev Mar 01 '16 at 06:57
  • 2
    *Right?* No, wrong. If you mean that there is a "tick" between the call to `p.then` and the `console.log`, there is not. The `console.log` will execute instantly after the `p.then`, before the handler has a chance to execute, since that won't happen until the next tick. –  Mar 01 '16 at 07:30
  • 1
    Yep. I assume there are many ticks between `p.then` and `consol.log`. If there are no thicks then the promise is not resolve and the value of isResolved is false, which is the correct behaviour. After some more ticks when the promise is resolved, isResolved will be true which is again the correct behaviour. – nstoitsev Mar 01 '16 at 07:33
  • 8
    As someone familiar with how browsers work I understood the comment `... At some point in the future.` but if I was a new to JavaScript I think I might be mislead into thinking that if put `for (let i =0; i < 1000000; ++i);` before the log it would somehow return true as written. (to be clear it will never be true unless the code exits the current event) – gman Feb 01 '18 at 03:53
  • @AmanGupta is correct. The value of isResolved will always be false because when the code starts executing `.then()` it'll be executed in the next event loop and it'll simply just skip to the `console.log` statement. And later when the `.then` is executed it'll change isResolved to true. But this value will never be seen since the `console.log` has already been executed – Yash Kalwani Apr 30 '18 at 22:43
  • This is the solution I will use because I'm in an async function where I'm checking `isResolved` after awaiting another Promise. If you are in a synchronous function, make sure that you're checking isResolved at least in the next tick. If you're in an asynchronous function doing something as simple as `await Promise.resolve()` might do the trick. – Mehmet Efe Akça Mar 30 '21 at 18:09
  • 1
    @AmanGupa, this answer is correct. Because there is a bunch of not-written-yet code above the `// ... At some point in the future.` comment that was not included in the answer. You could fill in this unwritten code with a recursive timeOut and a console log to see the desired results. – TamusJRoyce May 21 '21 at 04:42
  • that should be resolve in es8. if you need to write whole app that relies of promise being resolved putting everythin inside .then() block is insane – Sebastian Dec 17 '21 at 18:47
  • you haven't had to put everything inside a .then() block since we had async await... but man, you should have been around back before ES6, when we had to deal with callback hell and literally put everything inside nested functions! – Kyle Baker Oct 07 '22 at 09:04
40

Quoting the MDN documentation:

By design, the instant state and value of a promise cannot be inspected synchronously from code, without calling the then() method.

So, you need to call the .then method.

ashish
  • 750
  • 5
  • 12
  • 1
    Both answers were good, so I flipped a coin and it landed on the other answer. Thanks for the answer though! – trusktr Mar 01 '16 at 06:57