Search code examples
angularpromiseobservablewait

Angular 5+ wait for service that returns a promise


I have a service call that returns a promise, but when I try to set the return type as promise I'm having trouble using it in the caller function due to the type not being recognized, so it won't compile.

So I have tried using the below method, but I run into a timing issue (code executes before call finishes)

  private getSomeData(): DataObjectArray[] {
    return this.myService.something().map((response: Response) => {
      return response.children;
    });
  }

  public compileData(): DifferentDataArray[] {

   // get some stuff from a config, then make service call
    let someData = this.getSomeData();

    /* If I have a promise returned, someData errors saying not an array type */
    for (let oneData of someData){
      /* loop through config data + service data making a return object array */
   }
    return this.dataCollection;
  }

Solution

  • I recommend in Angular you try to keep things as observables. Its nice to be consistent, instead of flipping back and forth between observables and promises.

    I'm not super clear if myService.something() returns a promise or an observable. If observable:

      private getSomeData(): Observable<<DataObjectArray[]> {
        return this.myService.something().pipe(
           map(response => response.children)
        );
      }
    

    if its a promise very similar but:

        private getSomeData(): Observable<<DataObjectArray[]> {
          return fromPromise(this.myService.something()).pipe(
           map(response => response.children)
          );
        }
    

    Then:

      public compileData(): Observable<DifferentDataArray[]> {
    
       // get some stuff from a config, then make service call
        return this.getSomeData().pipe(
           map(someData => {
               /* If I have a promise returned, someData errors saying not an array type */
               var dataCollection = [];
               for (let oneData of someData){
                /* loop through config data + service data making a return object array */
                     // should dataCollection.push(changedData);
                }
                return dataCollection;
           });
        );
    
      }
    

    Finally to consume somewhere else:

         this.compileData().subscribe(compiledData => {
             // do something with the compiled data
         });
    

    Notes: The pipe operator is pretty powerful. It takes an observable, and lets you do some work on it before returning it. In this case, I used the map operator, because you are just changing the shape of the return a little bit. At the end of the chain, you must always subscribe to an observable to get the data back (per the last black in my example)