[Fixed] JavaScript – merging results from two API calls

Issue

I have a straightforward Angular component (Ionic) which makes:

  1. an API call to get some data (returned as an Observable) and
  2. gets data from a SQLite database stored on the device (returned as a Promise)

I am trying to merge the two results.

Here is my component:

import { Component, OnInit, Output } from '@angular/core';
import { merge } from 'rxjs';
import { Fact } from '../fact';
import { Label } from '../label';
import { DashboardService } from '../services/dashboard.service';
import { DatabaseService } from '../services/database.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.page.html',
  styleUrls: ['./dashboard.page.scss'],
})
export class DashboardPage implements OnInit {
  rows: Fact[];
  labels: Label[];

  constructor(
    private dashboardService: DashboardService,
    private database: DatabaseService
  ) {
    this.refreshDashboard();
  }

  ngOnInit() {}

  refreshDashboard() {
    console.log('refreshing...');
    this.getDashboardData();
    // Get labels
    this.database
      .createDatabase()
      .then(() => {
        this.getLabels();
      })
      .then(() => {            
        console.log(this.rows.length); // ******* UNDEFINED *******
        console.log(this.labels.length); // ******* UNDEFINED *******
      });
  }

  // Coming from an API call, which returns an Observable
  getDashboardData() {
    this.dashboardService.getData().subscribe((data) => {
      this.rows = data;
    });
  }

  // Coming from local SQLite database
  getLabels() {
    this.database
      .getLabels()
      .then((data) => {
        this.labels = [];
        if (data.rows.length > 0) {
          for (let i = 0; i < data.rows.length; i++) {
            this.labels.push(data.rows.item(i));
          }
        }
      })
      .catch((e) => {
        alert('There was an error: ' + e);
      });
  }

  // mergeResults()
}

I cannot figure out how to ensure that the two variables rows and labels have been populated before I can use them inside mergeResults().

Solution

then() must be nested when the order matters. So

  dosomething1.then( ()=> {
     dosomething2.then( () => {
       dosomething3.then( () => {
         console.log("hey");
                       })
                     })
                   })
                

In your case that would mean

 refreshDashboard() {
    console.log('refreshing...');
    this.getDashboardData();
    // Get labels
    this.database
      .createDatabase()
      .then(() => {
        this.getLabels();
      })
      .then(() => {  <---This here has no use at all. Nothing returns a promise here           
      });
  }

  // Coming from an API call, which returns an Observable
  getDashboardData() {
    this.dashboardService.getData().subscribe((data) => {
      this.rows = data;
    });
  }

  // Coming from local SQLite database
  getLabels() {
    this.database
      .getLabels()
      .then((data) => {
        this.labels = [];
        if (data.rows.length > 0) {
          for (let i = 0; i < data.rows.length; i++) {
            this.labels.push(data.rows.item(i));
          }
        }
        console.log(this.rows.length); // here you expect values to be ready
        console.log(this.labels.length); // here you expect values to be ready
      })
      .catch((e) => {
        alert('There was an error: ' + e);
      });

Leave a Reply

(*) Required, Your email will not be published