1

I am trying to resolve a Promise only after a certain condition is met outside the promise:

class myClass extends ... {

    render() {
       ...
       this.fetch();
       ....
    }

    fetch(){
        Promise.all([
          ....,
          ....,
          ....
        ]).then( () => {
          // new Promise or somthing like that
          // wait for state changed to resolve it
        }
        ).then(
          // do something
        )
    }

    stateChanged(state){
        if(condition){
           // resolve promise from here
        }
    }

}

I tried to implement it in similar way to this question Resolve Javascript Promise outside function scope but I do not understand

  1. how we can call a variable
  2. how to make this work inside my Class I tried it with a this.waitForPromise = null variable, but when I call it later this.waitForPromise() I get a is not a function Type error.
class myClass extends ... {

    render() {
       ...
       this.fetch();
       ....
    }

    constructor(){
        this._waitForPromise = null;
    }

    fetch(){
        Promise.all([
          ....,
          ....,
          ....
        ]).then( () => {
            new Promise(function(resolve, reject) { 
              this._waitForPromise = resolve; 
            });
        }
        ).then(
          // do something
        )
    }

    stateChanged(state){
        if(condition){
           this._waitForPromise();
        }
    }

}

Any help and explanation is much appreciated.

Georg RP
  • 25
  • 5

2 Answers2

1

You have a closure issue using this, so capture it first.

You should return the promise in your then.

You should check to see if promise is created when state changes.

Keep in mind you can only invoke one of resolve/reject, and only once.

class myClass extends ... {

    render() {
       ...
       this.fetch();
       ....
    }

    constructor(){
        this.resolve = null;
        this.state = null; // TODO initial state
    }

    fetch(){
        const that = this;
        Promise.all([
          ....,
          ....,
          ....
        ]).then( () => {
            return new Promise(function(resolve, reject) { 
              that.resolve = resolve;
              that.checkState();
            });
        }
        ).then(
          // do something
        )
    }

    checkState(){
      if(condition && this.resolve){
         this.resolve();
         this.resolve = null;  // set to null to ensure we don't call it again.
      }
    }

    stateChanged(state){
        this.state = state;
        this.checkState();
    }

}
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
  • This is exactly what I tried but I receive a 'Uncaught (in promise) TypeError: this.resolve is not a function" error. – Georg RP Sep 22 '19 at 14:51
  • Did you capture `this` in a closure, and then reference it through `that`. `const that = this;`? In your original code, `this` refers to the promise, and not the containing class. – Steven Spungin Sep 22 '19 at 16:06
  • I am not 100% sure to be honest I tried it exactly the way you wrote it and then also with `..),bind(this)` but I always get the "is not a function" error. I think I get the Idea that we want to access the function scope of the Promise but I do not understand the concept behind `that.resolve = resolve;`. – Georg RP Sep 22 '19 at 16:34
  • that.resolve storing the resolve function in your class as a property. Then you invoke it in `stateChanged`. You will get a `is not a function` if your `this` is not pointing to your class when you assign it, and then call it from stateChanged. – Steven Spungin Sep 22 '19 at 17:02
  • Put a console.log(this) inside of stateChanged, fetch, and your Promise, and confirm they are all the same. – Steven Spungin Sep 22 '19 at 17:03
  • Ok, thanks so much that helped a lot for the understanding. So the problem seems to be that the Promise does not exist yet when I try to call `this.resolvse()` as the `Promise.all` was not fulfilled for all conditions yet. I tried putting it into directly into the Promise.all but no luck yet I will try a bit later or tomorrow morning. – Georg RP Sep 22 '19 at 17:47
  • You can put logic in the promise to resolve it if the state is set. I will update solution. You can see that `checkState` is called from both places to ensure there is no race condition. – Steven Spungin Sep 22 '19 at 19:36
0

OK, so I'm not all that familiar with Polymer 3, but I'm fluent in Polymer 1 and 2.

I'm getting that you want to do this:

  1. Get an ajax promise.

  2. Return said ajax promise once a certain state has changed.

  3. do a fetch call if said promise hasn't been done.

What you need to do is to save your promise as a variable, and then just chain it together with other method calls. The comments below explains more about what I'm doing with your example code from the OP.

class myClass extends ... {

render() {
   ...
   this.fetch();
   ....
}

fetch(){
    this.set('savedPromise', Promise.all([ // save promise to variable 
      ....,
      ....,
      ....
    ])
    // not needed
    /* .then( () => {
      // new Promise or somthing like that
      // wait for state changed to resolve it
    }*/
    ).then(
      // do something

      return result // added this line
    )
}

stateChanged(state){
    if(condition){
       if (this.savedPromise) {
         this.savedPromise.then(function(response) {
           // handle data
         });
       else {
         fetch().then(function(response) {  // if set before render(), do a fetch call.
           // handle data
         }
       }
    }
}

}

Rickard Elimää
  • 7,107
  • 3
  • 14
  • 30