Angular 5 - Empty array containing objects has a length of zero

In my app.component.ts file, I have an array initialized to load objects in the onInit event:

ngOnInit() {
this.pages = [];
}

Within the ngOnInit event, I also have a setInterval method that evaluates an expression every few milliseconds:

setInterval(() => {
  if (!this.isUser && !window.location.href.toString().toLowerCase().includes('localhost')) this.setUser();
}, 1000);

Inside the "setUser" method, I populate the "pages" array by making API calls within a loop.

private setUser() {
    for (let i = 0; i < this.components.length; i++) {
      const component = this.components[i];
      this.http.get(urlApi + component).subscribe((data: any) => {
         let url = this.getURLComponent(component);
         if (url) {
           if (data) {
             this.pages.push({
               url: url,
               allowed: true
             });
           } else {
             this.pages.push({
               url: url,
               allowed: false
             });
           }
        }
      });
    }
    this.testAllowedComponents(pages);
}

Within the same "setUser" method, after exiting the loop, I call another method passing the array of objects as a parameter:

testAllowedComponents(pages: any[]) {
    console.log('pages: ', pages);
    console.log('pages length', pages.length);
}

The issue arises when accessing the "testAllowedComponents" method – the first console displays the correct content of "pages," but the second console shows a length of 0.

What could be causing this problem? Is it due to asynchronicity when executing the loop inside the setInterval function?

Answer №1

One of the key issues at hand is synchronization when dealing with AJAX requests. When you send an AJAX request, it will trigger the callback function asynchronously. As a result, any methods following this callback will execute immediately without waiting for the callback to finish. This determines the order of execution:

console.log("Order 1"); // First call
this.http.get("/api").subscribe(()=>{
   // Last time it will run
})
console.log("Order 2"); // Immediately follows the first call

In your situation, when iterating through a for-loop, the testAllowedComponents method will be called after each iteration. However, since the AJAX request's timing is uncertain, it may or may not coincide with these iterations. To address this, you can synchronize using RXJS and array operators. Here are the steps:

  • Convert the components array into a stream.
  • Transform these streams into AJAX request streams.
  • Encapsulate all logic inside the subscribe method.

Solution:

private setUser() {
    // Components array converted into streams
    const streams$ =from(this.components)
         .pipe(swictchMap((comp)=>this.http.get(urlApi + comp)
         .pipe(map((response)=>({ data:response,comp:comp }))));

    from(streams$).subscribe(({comp,data})=>{
      let url = this.getURLComponent(component);
     if (url) {
       if (data) {
         this.pages.push({
           url: url,
           allowed: true
         });
       } else {
         this.pages.push({
           url: url,
           allowed: false
         });
       }

       this.testAllowedComponents(pages);

    })

The most challenging aspect here could be the initial step, so let me elaborate. We are converting all components into observables, then transforming them into AJAX request streams after each iteration. This allows us to obtain the AJAX response as the component object and subsequently invoke the subscribe method, triggering the testAllowedComponents function post each iteration.

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

Developing an array in Angular on an Android device is proving to be a sluggish

I'm facing an issue with my simple array that collects rows from a database and uses a distance column as a key. let output = {}; for (let dataRow of sqllite.rows) { output[dataRow.distance] = dataRow; } When testing in Chrome browser on my PC, ...

Tips for dynamically populating a mat-table dataSource

While working with backend data streaming, I encountered an issue where trying to push an event to dataSource resulted in an error stating that dataSource is not defined. Can anyone provide guidance on how to dynamically add data to a materialize table? s ...

Allow Nest.js server to receive binary files in the request body

Is there a way to retrieve the uploaded binary file data from the browser? While the Nest.js server application functions correctly with Postman, it throws a 400 error when the request is sent from the Google Chrome/Angular application. Any ideas on how ...

npm ERROR! The requested resource at http://registry.npmjs.org/amcharts4 could not be located - Error 404: Resource Not Found

I'm running into an issue while trying to include npm package dependencies in my Angular project. Can anyone assist me in resolving this error? C:\Users\TM161\Desktop\Master\stage PFE\SNRT-Music>npm i npm ERR! code ...

Maintaining the order of subscribers during asynchronous operations can be achieved by implementing proper synchronization

In my Angular setup, there is a component that tracks changes in its route parameters. Whenever the params change, it extracts the ID and triggers a function to fetch the corresponding record using a promise. Once the promise resolves, the component update ...

customize your selections in p-multiselect with dynamic choices primeng angular 2

I am currently working on implementing the Primeng datatable. I have put together an array containing headers, fields, and options called headersList. Here is how it looks: { header: "Time", field: "time", options: "timeOptions" }, { header: ...

What is the best way to transfer two distinct states from my ngrx effect to my service function?

I am encountering a dilemma with my effects function, where I am attempting to pass data from a dispatched action and a separate selector to a service function. However, I am finding myself confused by the RXJS syntax and suspect that I may not be mapping ...

Using Typescript for-loop to extract information from a JSON array

I'm currently developing a project in Angular 8 that involves utilizing an API with a JSON Array. Here is a snippet of the data: "success":true, "data":{ "summary":{ "total":606, "confirmedCasesIndian":563, "con ...

Ways to ensure that your Angular component.ts file is executed only after the body has completely loaded without relying on any external

I am attempting to add an event listener to an element created with a unique identifier using uuid, but I keep getting an error that states "Cannot read properties of null (reading 'addEventListener')" export class CommentItemComponent implements ...

Avoid using <input oninput="this.value = this.value.toUpperCase()" /> as it should not convert the text displayed on the "UI", rather it should send the uppercase value

<input oninput="this.value = this.value.toUpperCase()" type="text" id="roleName" name="roleName" class="form-control width200px" [(ngModel)]="role.roleName"> Even though the UI is changing ...

What steps should I take to fix this Angular 8 error?

Encountered an issue in ../node_modules/@angular/http/src/backends/jsonp_backend.d.ts:1:28 - error TS2307: Module 'rxjs/Observable' not found. 1 import { Observable } from 'rxjs/Observable'; ~~~~~~~~~ ...

Angular and the challenges of connecting Facebook OAuth due to CORS problem

In my API, I have implemented OAuth login and callback methods for popular platforms such as Facebook, Google, and Twitter. The API is built using Express.js framework and it runs on port 3000. Meanwhile, I also have an Angular 2 application running on p ...

Bidirectional communication linking an Angular 2 component and service utilizing the power of Observables

I'm having difficulties establishing a simple connection between an Angular 2 component and service using Observable. I've been trying to achieve this, but I can't seem to get it right. Here's the scenario: My component HeroViewerCompo ...

Implementing canActivate guard across all routes: A step-by-step guide

I currently have an Angular2 active guard in place to handle redirection to the login page if the user is not logged in: import { Injectable } from "@angular/core"; import { CanActivate , ActivatedRouteSnapshot, RouterStateSnapshot, Router} from ...

Having trouble with uploading the profile image in Angular 2? The upload process doesn't

I just started learning Angular and decided to create a profile page. But, I encountered an error while trying to upload a profile image. The error message that I received was POST http://localhost:3000/api/v1/users/avatar/jja 500 (Internal Server Error). ...

Demystifying the Mechanics of RxJS Subscriptions during an HTTP Request

export class VendorHttpService { result = '0'; constructor(private http: HttpClient, private global: GlobalService) { } getProfileStatus(uid: String): string { this.http.get(this.global.getUrl()+"/vendor/profile-status/"+uid) ...

Having difficulty retrieving an angular file from a location outside of the asset folder

I'm encountering issues with a small project that is meant to read a log and present it in table format. Here is the outline of the project structure: project structure Within the LOG directory, I should be able to access motore.log from my DataServi ...

Using an Angular HttpClient to authenticate with an API by utilizing a token for

I am currently attempting to fetch data from my Jenkins JSON API via HTTPClient. The data I need access to is restricted, so I must authenticate against Jenkins. To do this, I have generated an API Token. However, I am unsure of how to authenticate myself ...

How to filter an array in Angular 4 without the need for creating a new array and then displaying the filtered results within the same

In my collection of students, I have their names paired with their academic outcomes. studentResults = [ {name: 'Adam', result : 'Passed'}, {name: 'Alan', result : 'Failed'}, {name : 'Sandy', result : &ap ...

Sharing API Results with All Components in Angular 7 using BehaviorSubject

My goal is to optimize an API call that fetches data about the current user (such as their username, full name, group memberships, email address, and more) by ensuring it's only made once per user session and that the data is shared across all compone ...