0

Is it possible to save the resolve function of a Promise outside of the executor function, i.e. in a class variable so that it could be triggered by other ongoing routines like other methods?

Something like that:

class Foo {
    constructor() {
        this.promise = new Promise((resolve, reject) => {
            this.resolve = resolve;
        });

        doSomething();
    }

    doSomething() {
        //...
        this.resolve();
    }
}

Update: the larger context

The upper code is just pseudo-code to show what I mean. I'm working on a React application and therefore my code is not pure JavaScript but TypeScript.

In the class where I try to do this Promise trick, let's call it AppHelper, there are two important methods:

  1. initAppInfo starts a Promise to get it's own version number (which actually calls a Capacitor API - or if it fails (i.e. when running in Browser) it falls back to read that info from manifest.json using fetch - which is a nested Promise)
  2. didUpdateApp which can be called by other React components and should return, whether the app's version number changed in contrast to the last session. Because we're talking async, of course it does not simply return a boolean.
    • I thought about returning a Promise, which itself does not execute anything, because the relevant task is already running.
    • An alternative I could think about is to accept callbacks as a parameter to this method and collect them in an array for later execution. But I thought it would be nice to have the widely known Promise API and Promises are especially nice due to the fact, that a later initialized component can attach another .then() even if the Promise has already finished and it's still getting executed.

Do you have better ideas which approach could solve that elegantly?

(The real code does many more things and I would have to paste at least two files and explain more about the whole structure, Capacitor, Ionic, etc. that's why I tried to explain it more detailed for now. But if you think it's still necessary/helpful to see it, I will add it in another update to my post.)

Robert
  • 440
  • 7
  • 19
  • 1
    Why not just try it? Yes – CertainPerformance Nov 11 '21 at 23:43
  • yes, it is possible – Andrei Nov 11 '21 at 23:43
  • 1
    Read up on the "deferred" pattern. – jonrsharpe Nov 11 '21 at 23:44
  • 1
    Yes, it's possible, but not advisable. The code in your question has syntax errors as you cannot declare `var`s inside a `class` body though. – Bergi Nov 11 '21 at 23:48
  • 2
    Here's [an example](https://stackoverflow.com/questions/37651780/why-does-the-promise-constructor-need-an-executor/37673534#37673534) of encapsulating the `resolve()` and `reject()` callbacks into a Deferred object so code outside your promise callback can resolve or reject the promise. Note, it is very rare that this design pattern is actually necessary. Over 99% of the time, there is a better way to structure your code that does not require exposing the resolve callback. – jfriend00 Nov 11 '21 at 23:51
  • 2
    If you show the larger context of what you're trying to do here with real code (not pseudo-code), we can perhaps suggest a way to approach the problem that does not require exposing the `resolve()` function. There's a reason that there is no Deferred object built into Promise support. – jfriend00 Nov 12 '21 at 00:04
  • @CertainPerformance Of course I tried and it worked in some cases but not every time. I could not yet find out whether it has something to do with React or my other codes. And I wanted to know, whether that's ugly/something that works but maybe not in every browser or should not be done/etc. – Robert Nov 12 '21 at 01:25
  • Are you trying to initiate asynchronous operations in the constructor? Is that the source of this issue? If so, you can see the factory function design pattern [here](https://stackoverflow.com/questions/49905178/asynchronous-operations-in-constructor/49906064#49906064) which is often a cleaner way to implement that. You don't expose the constructor directly. Instead, you expose a factory function that creates the object, initializes it and returns a promise that will resolve to the newly created object when all the asynchronous initialization is done. It's a very clean way to do it. – jfriend00 Nov 12 '21 at 01:28
  • So you want `didUpdateApp` use the promise that `initAppInfo` had created? Just store it on the instance and use it, you don't even need the promise constructor for that. Also consider what will happen if `didUpdateApp` is called before `initAppInfo`, without "*the relevant task already running*". – Bergi Nov 12 '21 at 01:28
  • @Bergi No, `initAppInfo` just wait's for detecting the app's version and then stores it in a variable and finally compares it to the last value. Getting the **current** version and **detecting that it's bigger** than the version, that was stored in LocalStorage when the app initialized the last time, are two different things. And I like to allow to call `didUpdateApp().then()` before `initAppInfo` and the following comparison have finished. Or did I get you wrong? – Robert Nov 12 '21 at 01:38
  • @jonrsharpe Thank you! Using that keyword I found [this answer](https://stackoverflow.com/a/34637436/1255674) with the same subject – Robert Nov 12 '21 at 01:43
  • Closed as duplicate base on OP's own comment of finding a solution in another question – slebetman Nov 12 '21 at 02:08

0 Answers0