0

What is the standard built-in JavaScript function to create an abstract promise? By abstract, I mean that I can attach dependencies before or after the resolution method is defined.

For instance, I'd like to be able to just write:

// page load sequence
let Cli_Cfg      = New_Promise(); // client configuration loaded
let Initial_View = New_Promise(); // complete view is displayed

Cli_Cfg.then((cfg)=>console.log(cfg)); // does not print
Cli_Cfg.resolve("client config");      // prints "client config"
Cli_Cfg.then(()=>console.log("MORE")); // prints "MORE"

The problem with simply using new Promise(f) is that, case by case, I have to write a function f that immediately starts doing work towards resolving the promise. But in my example above, the means to actually load the client configuration is not even defined until 15 other things are fetched, initialized, cross-consulted, compiled, and baked.

As a hack, I came up with this:

function New_Promise()
{
  let resolve;
  let result = new Promise(r => resolve = r);
  result.resolve = resolve;
  return result;
}

What is the built-in function that does this? (Or, if you think none exists, please give a reason why the language standard committees might have rejected this obvious idea.)

personal_cloud
  • 3,943
  • 3
  • 28
  • 38
  • Do i understand it correctly. That you want to create a promise, and then run it later? – Marko Taht Nov 29 '22 at 17:14
  • @Marko Yes. More specifically, I want to create a promise without saying anything about how to fulfill it. And immediately start `then`ing it, before saying anything about how to fulfill it. – personal_cloud Nov 29 '22 at 17:16
  • I think there's a legit use case for this kind of thing, but it always comes back to leaking `resolve` and `reject` parameters out of the callback supplied to the Promise constructor. I don't think there's any other way (other that an abstraction that uses this technique within). If you discount the more "chatty" elements of your question, [this has already been answered](https://stackoverflow.com/questions/26150232/resolve-javascript-promise-outside-the-promise-constructor-scope) – spender Nov 29 '22 at 17:16
  • @spender Thank you for linking a related question. Note that that question does not have the "Or, if you think none exists, please give a reason why the language standard committees might have rejected this obvious idea" part. But you're right that some of the answers touch on it. – personal_cloud Nov 29 '22 at 17:19
  • As far as i know there is no direct way to do this. Leaking resolve and reject seems to be the only way. While there is a usecase for things like this. Its not very common, and it can be resolved with builder. Just make a promiseBuilder. Add all the thens and resolves you want. And then make a method run(function to be run). and run method returns JS promise that is constructed based on what you added to the builder. – Marko Taht Nov 29 '22 at 17:23
  • Another option would be to create a wrapper promise class. That extends the inbuilt promise. Then it would work like normal, but you can add in the run method for it. – Marko Taht Nov 29 '22 at 17:29
  • @Marko Thank you for teaching me about the builder pattern. Which version are you thinking of? [This one](https://www.dofactory.com/javascript/design-patterns/builder) seems to require more steps than I want. Specifically, I don't have a "director". I'm not specifically launching a set of steps in order to resolve a promise in isolation. For example, I'm dynamically building a set of structures, and, along the way, some of the promises get resolved as certain combinations of structures get to certain steps. Also the builder I linked doesn't seem to even have a `then` queue. – personal_cloud Nov 29 '22 at 17:48
  • What you are after is often called a [Deferred](https://stackoverflow.com/questions/46203393/pure-javascript-deferred). jQuery has it. I'm quite sure there is always a way to convert code to use the Promise pattern instead of the Deferred pattern, without losing elegance. – trincot Nov 29 '22 at 18:07
  • I mean, use the builder pattern to build a promise. And then "execute" it when you need it to be executed. Like you dont have a promise, until you invoke run or build or something. Or just extend the existing Promise to work like Deffered, like trincot described. Or find some JS module to use that does this for you. – Marko Taht Nov 29 '22 at 18:11
  • "*In my example above, the means to actually load the client configuration is not even defined until 15 other things are fetched, initialized, cross-consulted, compiled, and baked.*" - then you should not use `new Promise`. You should write `Cli_Cfg = fetchInitialiseCrossconsultCompileAndBakeMeans().then(means => means.loadClientConfiguration())`. – Bergi Nov 29 '22 at 21:20
  • "*please give a reason why the language standard committees might have rejected this obvious idea*" - because it's the wrong approach to use promises. It may be obvious when thinking of a promise as a writable variable, but it isn't. It's a result value, composed from chaining other promises, or produced from a simple async action as a small single building block. A promise is returned from the component that is resolving it, it is not meant to be resolved by anyone who gets its hand on the object. – Bergi Nov 29 '22 at 21:28

0 Answers0