10

I've seen that the native ES6 Promise.resolve() can be invoked directly - as a static method. Facebook is using it that way in their Flux examples.

But in what case should I do that? To queue something? Or instead of using window.setTimeout()?

kraftwer1
  • 5,253
  • 10
  • 36
  • 54

3 Answers3

19

You should call Promise.resolve(object) when you need to create a promise that is already resolved. For example you may have a function that starts downloading a resource from the server or returns its cached version:

function getImage(imageUrl) {
    if (imageUrl in this.cache) {
        // no need to download, return immediately
        return Promise.resolve(this.cache[imageUrl]);
    } else {
        return new Promise(function(resolve, reject) {
            // start downloading and eventually resolve
        });
    }
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Sergey Rybalkin
  • 3,004
  • 22
  • 26
  • Only to be able to call `then()` on it? – kraftwer1 Sep 08 '15 at 15:11
  • Yes, this is required if the calling code expects promise to be returned. Thus you won't break the calling convention, see more examples here - http://devdocs.io/javascript/global_objects/promise/resolve – Sergey Rybalkin Sep 08 '15 at 15:13
  • 2
    The use of "*already resolved*" is misleading. The returned promise doesn't have to already be resolved, and the callback of a `then()` call on the returned promise will not necessarily be invoked "very soon" (next cycle..), and can take an infinite amount of time depending on what was posted into the `resolve` call. – Amit Sep 08 '15 at 21:25
  • 1
    I agree with @Amit, I think "create a promise in a case where it _might_ already _be_ resolved" fits better. Great example, it illustrates a practical use case. – kraftwer1 Sep 09 '15 at 07:33
  • @Amit: Actually, "already resolved" is [technically correct](http://stackoverflow.com/a/29269515/1048572). It might not yet (and maybe never) be settled, though. – Bergi Sep 09 '15 at 10:44
  • @Bergi: `var p = new Promise(() => {}), r = Promise.resolve(p); p === r`, and `p` / `r` (same) is not resolved, infact, `console.log(r)` shows *[[PromiseStatus]]: "pending"*. So technically it can be unresolved, but since the example "resolves" a value (object...) that's not a promise, it will be resolved. – Amit Sep 09 '15 at 12:03
  • @Amit: Ah, right, I forgot that `Promise.resolve` might return the input. Yet that should be indistinguishable from `r = new Promise(res => res(p))` in behaviour; and I'd argue that you could say "*r is resolved to p*" in both cases. – Bergi Sep 09 '15 at 12:49
  • 1
    @Bergi - I'd mostly say we're discussing how wet the ocean is - it makes no real-world difference :-) – Amit Sep 09 '15 at 12:51
3

Promise.resolve(42) is just a shorthand for

new Promise(function(resolve) {
    resolve(42);
});

So whenever you find yourself doing something like this, i.e. creating a promise from an existing value, you can use Promise.resolve instead.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
2

Semantically, functions that return promises are asynchronous functions, and, as you know, can be chained together:

a().then(b).then(c).catch(failure);

While synchronous functions can be part of asynchronous chains as well, this only works because the .then function automatically promotes return values from the functions you pass it, to promises. E.g. If b and/or c return values that are not promises, then the chain still works, but if a returns a non-promise value then that's TypeError.

In most cases you probably know what areturns, so this is fine, but in cases where you don't know what a will return (say you're doing generic programming), then you can do this:

Promise.resolve(a()).then(b).then(c).catch(failure);

a, b and c are now treated the same in this regard:

  • If a returns 1, then b will be called soon with 1.
  • If a returns a promise, then b will be chained behind a.

The method Promise.reject accomplishes the same thing for failure chains.

Additonally, these methods can be handy in cases where you just need a promise that resolves right away. E.g.

[a, b, c].reduce((p, f) => p.then(f), Promise.resolve()).catch(failure);
jib
  • 40,579
  • 17
  • 100
  • 158
  • 1
    They are not treated equally though when one of them throws. You may consider using `Promise.resolve().then(a)…` instead. – Bergi Sep 09 '15 at 10:42
  • 1
    @Bergi good point, thanks for that. The two ways differ slightly, so make sure to pick the one that's right for you. If `a` truly is the first method in a new sequence and it has a synchronous component to it, then it may be desirable to ensure its synchronous part has run before one returns (most browser APIs at least strive to do input validation synchronously to make them observable in the js debugger by inspecting the promise state and reason), or maybe just to avoid the extra dispatch. But if `a`, `b` and `c` are true equals then what you suggest may be preferable. – jib Sep 09 '15 at 14:09