Ways to execute functions in a sequence in Angular 2/4 with Typescript

I'm struggling with running functions sequentially in my Angular 2/4 project. I have a retrieveData() function that fetches data from a service and stores it in an array. Then, there's a displayData() function that uses this data to create a chart. However, when I try to run them one after the other, like this:

function(){
  this.retrieveData();
  this.displayData();
}

The issue is that the displayData() function runs before retrieveData(), causing problems with displaying the graph correctly.

I've considered using async.waterfall from the async library but faced difficulties importing it into my project. The console gave me this error:

Uncaught Error: Unexpected value 'waterfall' imported by the module 'AppModule'. Please add a @NgModule annotation.

I prefer not to use Promises or Observables as they require return values from the initial function to pass on to the next ones. Although I tried using setTimeout() to manage sequential execution, I worry about its reliability.

Any suggestions on effectively utilizing async with Angular 2/4 or any alternative methods for making functions wait without relying on return promises?

UPDATE

Apologies for the confusion earlier. Here's a more complete snippet of my code. I'm new to Angular and TypeScript, especially when it comes to asynchronous programming techniques.

Below is my attempt at implementing promises in the retrieveAllData() method. It compiles and runs without errors, but the functions still execute asynchronously, with refreshAllCharts() occurring before retrieveAllData(). Is there a flaw in how I'm handling promises?

Code snippet: (Your provided code)

Answer №1

When working with promises, it is not necessary to return a value in order to move on to the next functions. If you prefer to maintain the original function signatures of retrieveData() and displayData(), where they do not require any parameters and return void, you can utilize promises in the following manner:

private dataStorage: string = null;
private retrieveDataResolver;

  displayData(): void {
    // code for displaying data goes here
    console.log("2. DISPLAYING DATA", this.dataStorage);
  }
  retrieveData(): void {
    // logic for asynchronously retrieving data goes here
    console.log("1. GETTING DATA FROM SERVER");
    setTimeout(() => { 
      this.dataStorage = '++DATA++';
      this.retrieveDataResolver(); 
    }, 1000);
  }

  retrieveDataPromise(): Promise<any> {
    return new Promise((resolve) => {
      this.retrieveDataResolver = resolve;
      this.retrieveData();
    })
  }
  retrieveAndThenDisplay() {
    this.retrieveDataPromise().then(() => {this.displayData()});
  }

I suggest using promise wrappers as a robust chaining mechanism for coordinating asynchronous operations.

Answer №2

Adjacent to your latest update, you have the option to link promises together. Initially retrieve the data, and trigger a graph refresh once the data is available. For a deeper understanding of promises, check out this resource: https://example.com/promises-tutorial

// Retrieve data
var promise1 = new Promise(function(resolve, reject){
    resolve('complete');
});


promise1.then(function(data) {
    refreshGraph();
})

Answer №3

If you're struggling to understand async concepts in rxjs terms, there's a helpful website that breaks it down in a more accessible way compared to the complex rxjs documentation.

According to them, this code snippet serves as an alternative to the async waterfall function:

var Rx = require('rx');

var async = {
    waterfall: series => {
        return Rx.Observable.defer(() => {
            var acc = series[0]();
            for (var i = 1, len = series.length; i < len; i++) {

                // Utilizing func for closure capture
                (function (func) {

                    // Applying flatMapLatest on each function
                    acc = acc.flatMapLatest(x => func(x));
                }(series[i]));
            }

            return acc; 
        });
    }
}

To implement this, you would utilize fromCallback for the initial call and fromNodeCallback for subsequent calls in order to link the results together in the sequence.

Answer №4

Consider trying a structure similar to the following:

 getDataFromAPI(): Promise<any> {
      return this.apiService.fetchData(this.device, this.selectedDate)
          .map(response => response.json())
          .toPromise();
  }

  executeDataFunctions() {
      this.getDataFromAPI()
          .then(response => {
              for(var item of response){
                var value = item.Date;
                var time = moment.tz(value, "Asia/singapore");
                _arr.push(time);
              }
              this.timeArray = _arr;
              console.log("Time Array: " + this.timeArray);
              return response 
          }).then(response => {
              displayProcessedData();
          })
  }

The getDataFromAPI function retrieves data using the apiService and returns a promise.

By calling executeDataFunctions, it triggers the fetchData function first. Once the data is successfully fetched, it processes the data similarly to how you handled it in your initial code (using the response iterator).

Once data processing is done, it proceeds to the next step by returning the response. Subsequently, the execution continues with displaying the processed data after all operations are completed.

This setup should theoretically work, although exact testing remains pending.

Answer №5

Modern javascript architecture prioritizes asynchronous design for improved user interface experiences. With this approach, HTTP get requests are initiated without pausing program execution. Instead, the program continues to run until the data is ready, at which point a notification is received and the data can be utilized.

To achieve this functionality, an Angular service must be implemented to handle data retrieval using observables.

import { Component, OnInit } from '@angular/core';
import { IntervalObservable } from "rxjs/observable/IntervalObservable";
// import data model
import { PositionsModel } from "./positionsmodel";
// import service for HTTP requests
import { MouvementService } from './mouvement.service';

@Component({
  selector: 'app-mouvementview',
  template: '<div  *ngIf="data">  
            <div>{{data.x1r'}} </div>
            </div> ',
  styleUrls: ['./mouvementview.component.css']
})

export class MouvementviewComponent implements OnInit {
  public data: PositionsModel;
  private display : boolean;

  // Inject mouvementService
  constructor(private mouvementService: MouvementService) {
    this.display = false;
    }

  ngOnInit() {
      this.mouvementService.getPositions()
      .first() // only gets fired once
      .subscribe((data) => {
        this.data = data;
        this.display = true;
        /* Refresh chart */
      });
      // if periodic refresh is needed
      // get data every subsequent 200 milliseconds
      IntervalObservable.create(200)
        .subscribe(() => {
          this.mouvementService.getPositions()
            .subscribe(data => {
          console.log(data);
          this.data = data;
          /* refresh chart */ 
            });
        });
   } 
}

Here is the HTTP service:

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from "rxjs";
import 'rxjs/Rx';
import { PositionsModel } from "./positionsmodel";

@Injectable()
export class MouvementService      {

constructor(private http: Http) {}

getPositions(): Observable<PositionsModel> {
    // Make the HTTP request:
    console.log("Initiating HTTP get request");
    return this.http
      .get('http://192.168.1.170:8080/api/mouvements')
      .map((res: Response) => {
        return res.json();
      });    
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering a type error with React component children in TypeScript

A few days ago, I delved into learning React with TypeScript and encountered the following error: /home/sotiris/Github/ecommerce-merng-platform/admin/src/components/DashboardHOC/DashboardHOC.tsx TypeScript error in /home/sotiris/Github/ecommerce-merng- ...

What are the benefits of combining Express and Firebase?

Embarking on my journey to learn the MEAN stack, I initially planned to use Firebase instead of Mongo.db and Angular2 instead of Angular. However, I encountered difficulties when attempting to set up Angular2 with Express in a straightforward manner. Durin ...

Navigating between routes in Angular can lead to multiple subscriptions being created

One issue I've encountered is receiving multiple subscriptions as I switch between routes in my Angular application. Within my parent component, I have defined the following routes: <li routerLink="route1" [routerLinkActive]="[&apos ...

Navigating with Gatsby Link and leveraging TypeScript

I am currently utilizing Gatsby Link with TypeScript and I am looking to pass parameters to a linked component from the source component. The documentation provided by Gatsby states the following: Sometimes you’ll want to pass data from the source pag ...

Exploring the vast world of deep type information in the Typescript JSON

Examine the contents of the file data.json: { "au": { "name": "Australia", "market_id": "111172", "language_code": "en_AU" }, "br": { "nam ...

Tips for creating a window closing event handler in Angular 2

Can someone guide me on how to create a window closing event handler in Angular 2, specifically for closing and not refreshing the page? I am unable to use window.onBeforeunLoad(); method. ...

Capacitor and Angular: Trouble with appStateChange listener functionality

In my quest to solve a KPI, I am attempting to trigger a logEvent using the Firebase SDK when the user closes the application (specifically in an Ionic/Capacitor/Angular environment). However, I am facing numerous challenges trying to access the appStateCh ...

Transform a list of H1..6 into a hierarchical structure

I have a task to convert H1 to H6 tags from a markdown file into a JavaScript hierarchy for use in a Table of Contents. The current list is generated by AstroJS and follows this format [{depth: 1, text: 'I am a H1'}, {depth: 2: 'I am a H2}] ...

Error message: "Mismatched data types in Formik errors when utilizing TypeScript"

I have a customized input component for formik which includes an error label if one exists. When I print it like this: {errors[field.name]}, it works. However, {t(errors[field.name]?.toLocaleString())} does not work. import { FieldProps, FormikErrors } ...

Angular 4 applications do not come with TinyMCE embedded

I've been attempting to integrate the tinyMCE editor into an angular4 application, but unfortunately I encountered an error that reads: tinyMCE is not defined. https://i.stack.imgur.com/qMb5K.png I have been following the guidance provided by tin ...

Is there a method for the parent to detect changes in its output when passing around complex objects to its child?

I am facing a challenge with a complex object that is being passed down from a parent component to its child components. The child components further break down this object and pass parts of it to their own children, creating layers of complexity. At times ...

Guide to waiting for an event to finish in Angular

My component features a scorebar positioned on the left side, with game logic being managed by a separate game service. When a new player joins, I need to temporarily hide the scorebar, update the players array in the game.service, and then display the sco ...

Enhance the existing Angular date pipe formats by incorporating a localized format that includes only the month and year (for example, 05/2020 in English locale or 05.2020 in German locale)

Is there a way to customize angular date pipe formats to show only month and year, such as 05/2020 for 'en' or 05.2020 for 'de', while still maintaining localization? I am aware of creating a custom pipe, but specifying a format like &a ...

Does Nativescript successfully utilize AOT Compilation even with the `Compiler` package still included?

I'm running this command: npm run ns-bundle --android --build-app --uglify The command is successful (you can find the complete log here). After navigating to the report folder (generated by webpack-bundle-size-analyzer), I found these two files: ...

Angular 2 form with ng2-bootstrap modal component reset functionality

I have implemented ng2-bs3-modal in my Angular 2 application. I am now looking for a way to clear all form fields when the close button is clicked. Can anyone suggest the best and easiest way to achieve this? html <button type="button" class="btn-u ...

Setting a variable based on the stage of its deployment in a DevOps environment: What you need to know

Is there a way I can easily update a variable in a React app based on the stage of an Azure DevOps release pipeline? For instance, if I have dev, QA, and production stages set up, and I want to change the client ID in the auth configuration for each envi ...

Setting up "connect-redis" in a TypeScript environment is a straightforward process

Currently, I am diving into the Fullstack React GraphQL TypeScript Tutorial I encountered an issue while trying to connect Redis with express-session... import connectRedis from "connect-redis"; import session from "express-session"; ...

What is the best way to pass down SectionList prop types in TypeScript when using React?

I am working on creating a wrapper for SectionList in React Native that needs to accept all the standard props of SectionList along with some custom ones. How can I set up typescript to accommodate this? Here is what I have tried: import React from &apos ...

The exit code 1 was triggered in the npm-lifecycleindex.js file at line 285,

0 silly lifecycle <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bac9ced5c8d194c9cadbfa8b948a948a">[email protected]</a>~build.prod: Args: [ '/d /s /c', 10 silly lifecycle 'gulp build.prod --color --en ...

Observable subscription does not result in updating the value

One of the challenges I'm currently facing in my Angular application is the synchronization of data from a server. To keep track of when the last synchronization took place, I have implemented a function to retrieve this information: fetchLastSyncDate ...