1

Consider this code:

function foo() {
    return promiseFoo.then((res) => {
        //...
        //Construct a `promiseBar` object which is promise-like, 
        //but also has other uses.
        //...
        return promiseBar;
    });
}

foo().then((res) => {
    //Because `promiseBar` is promise-like, it was automatically resolved.
    //So now, `res` is, for example, a primitive string instead of the 
    //original `promiseBar` object
})

Is there any way to prevent the automatic resolution of promise-like objects?

Dave
  • 12,117
  • 10
  • 46
  • 52
  • 1
    I wonder if you could return an object instead of promiseBar, like return { myPromise: promiseBar }; – JohnnyFun Jun 22 '16 at 05:32
  • What exactly is "promise-like"? The check is strict http://www.ecma-international.org/ecma-262/6.0/#sec-ispromise – zerkms Jun 22 '16 at 05:32
  • @zerkms I picked up the term from the typescript team. But what I meant was just an object that inherits from Promise (but in js, that's pretty loose). @JohnnyFun Yes I think that would work (also removing the `.then` method would work). But both are a bit awkward if I'm implementing a user-facing API. But after some testing and a bit more thoughts, I think it may be impossible to directly stop the default behavior. Make an answer. I'll accept if no better ones come. – Dave Jun 22 '16 at 05:47
  • If it is a promise (and it is) - then it will be resolved, as per the standard. – zerkms Jun 22 '16 at 05:50
  • @zerkms The reason that I posted this question is because anything that exhibit Promise-like qualities will get resolved (sometimes unnecessarily). How do you think the underlying implementation detects whether or not an object is a promise? Given the plethora of Promise libs out there, some check for the existence of `.then`, some check for `instanceof Promise`, etc etc... So whether or not something is a promise is actually the worry here. – Dave Jun 22 '16 at 06:04
  • Same idea as @JohnnyFun - you can return a closure that returns your promise (`return () => promiseBar`). Then the receiver just needs to replace `res` with `res()`. I believe this approach is rather commonly used. – Amadan Jun 22 '16 at 06:15
  • @Dave: In fact all the proper implementations out there, including native ES6 promises, [check for the existence of the `then` method](http://stackoverflow.com/a/29437927/1048572) and nothing else. – Bergi Jun 22 '16 at 06:56
  • Possible duplicate of [Fulfill (don't resolve) promise with another promise](http://stackoverflow.com/q/32168194/1048572) – Bergi Jun 22 '16 at 07:04
  • @Bergi I'm tempted to close that one as a duplicate of this one since it's a much clearer and shorter question asking the same thing. Also, that one is about `resolve` and not returning mostly. – Benjamin Gruenbaum Jun 22 '16 at 07:08
  • @Amadan, Bergi: duly noted. As for the possible dupe, the other question isn't asking for a concrete solution. So I agree with Benjamin Gruenbaum – Dave Jun 23 '16 at 00:17

1 Answers1

3

You would wrap it in a container object and then open it with destructuring:

function foo() {
    return promiseFoo.then((res) => {
        //...
        //Construct a `promiseBar` object which is promise-like, 
        //but also has other uses.
        //...
        return [promiseBar];
    });
}

foo().then(([res]) => {
    //Because it is an array, promiseBar is not resolved here
});

To be fair, I've never actually had to do this myself in a few years of using promises, so I'm wondering what you're actually doing - please do share.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • In my specific case, I have a promise that needs to return a webdriver client object. But the object is being unnecessarily resolved because it shares promise-like functionalities. When it's being resolved, it's actually initializing a new selenium browser session. So I definitely don't want that to happen; the receiver of the webdriver client should resolve it on his own. – Dave Jun 23 '16 at 00:08