Ensure all promises are resolved inside of for loops before moving on to the next

Within my angular 11 component, I have a process that iterates through elements on a page and converts them from HTML to canvas to images, which are then appended to a form. The problem I am encountering is that the promise always resolves after the 'done' message is logged to the console. How can I ensure that all instances of the 'generateCanvasFromHtml' function complete before continuing with the script following the loops? Despite this sequencing issue, the functionality of the function itself works as intended.

generateImagesFromPlan(): void {
    this.imageGenerating = true;

    // Create an empty FormData object for the images to be submitted
    const formData = new FormData();

    // Retrieve all sections available on the plan
    const pdfSections = document.querySelectorAll('[data-pdfsection]');
    for (let section of pdfSections as NodeListOf<HTMLElement>) {
      const sectionNumber = section.dataset.pdfsection;
      console.log('sectionName', sectionNumber)
    
      const pdfComponents = section.querySelectorAll('[data-component]');
      console.log('pdfComponents', pdfComponents)
    
      for (let element of pdfComponents as NodeListOf<HTMLElement>) {
        const componentImageNumber = element.dataset.component;
        console.log('componentName', componentImageNumber)
      
        this.generateCanvasFromHtml(element).then(canvas => {
          canvas.toBlob((blob) => {
            formData.append(sectionNumber, blob, componentImageNumber + '.png');
            console.log('blob added');
          }, 'image/png');

        });
      }
    }

    for (let pair of formData.entries()) {
      console.log(pair[0] + ', ' + pair[1]);
    }
    console.log('done');
    this.imageGenerating = true;
  }

  generateCanvasFromHtml(elem: HTMLElement): Promise<HTMLCanvasElement> {
   
    const clone = elem.cloneNode(true);
   
    const targetWidth = 1200;
    const iframe = document.createElement('iframe');
    iframe.style.visibility = 'hidden';
    iframe.width = targetWidth + 'px';
    iframe.height = '0px';
    document.body.appendChild(iframe);
  
    const iframeDocument = iframe.contentDocument;
    iframeDocument.replaceChild(clone, iframeDocument.documentElement);

    const targetHeight = iframeDocument.documentElement.scrollHeight;
    iframe.height = targetHeight + 'px';
    console.log('targetHeight=' + targetHeight);
    
    document.body.removeChild(iframe);
    const options = {
      width: targetWidth,
      windowWidth: targetWidth,
      height: targetHeight
    };

    return html2canvas(elem, options);

  }

Answer №1

To handle multiple promises, you can use the Promise.all method.

The approach you should take is to create an array containing calls to the function generateCanvasFromHtml() based on items in the pdfComponents array, then pass this array to Promise.all.

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

What is the procedure for renaming an item within a basic array in Angular?

I am working on a project in Angular and have constructed an array. I am now looking to change the name of one of the items in this array. While I have figured out how to rename keys in an array, I'm still unsure about how to do so for its values. ...

Is the pipe operator in RxJS essential for utilizing store.select in NgRx?

While reviewing some code, I noticed a pipe operator used without a chain. Is this necessary or does it provide any benefits at all? Code snippet with pipe: this.store.pipe(select(currentUser)).subscribe(authState => {}); Code snippet without pipe: ...

Is there a way to insert data from one table into a MySQL Table in Drizzle and update the entry if it already exists?

My goal is to utilize Drizzle for inserting data into a table and updating it if the key already exists. In MySQL, the code would look like this: INSERT INTO myTable1(field1,field2,field3,field4) SELECT fieldOne,fieldTwo,fieldThree,fieldFour FROM myTable2 ...

What is the best way to incorporate data from a foreach method into a function call within an HTML string?

Having trouble calling a function with data from a foreach loop while generating HTML cards and buttons from an array. The issue seems to be in the renderProducts() method. /// <reference path="coin.ts" /> /// <reference path="prod ...

Challenges arise when trying to access environment variables using react-native-dotenv in React

I am currently working on two separate projects, one being an app and the other a webapp. The app project is already set up with react-native-dotenv and is functioning as expected. However, when I attempt to use the same code for the webapp, I encounter an ...

Encountering a 404 error with systemjs-angular-loader.js in a production environment

Currently, I am working on the most recent Angular/Quickstart project that utilizes systemjs-angular-loader.js to load app-relative HTML templates without the need for the moduleId property. During development and testing with "npm start" to serve pages, ...

Improving the process of class initialization in Angular 4 using TypeScript

Is there a more efficient method to initialize an inner class within an outer class in Angular 4? Suppose we have an outer class named ProductsModel that includes ProductsListModel. We need to send the ProductId string array as part of a server-side reque ...

While making changes, I was anticipating a "for-of" loop to be used instead of a "for" loop

There seems to be an issue with TSlint and its disapproval of using the traditional for(i=0; ...) loop. Consider this straightforward code snippet: this.filters['1','2','3'....]; for (let i = 0; i < this.filters.length; i+ ...

Guide to integrating a native web component into Vue3

After creating the renderComponent method to display a webcomponent, I attempted to use it in my componentView.vue file. export function renderComponent(el: Element, component: Component,props: VNodeProps,appContext: AppContext){ let vnode: VNode | undefin ...

Improving the management of user input in Lit components

I am seeking a more efficient method to manage all inputs within my lit component while minimizing the code usage. I am also employing Typescript in this process, utilizing @change=${this.handleInput} for all input fields. Below is an example of how the ha ...

Stop the current HTTP request and initiate a new one asynchronously

My custom component showcases a detailed view of a selected building along with a list of its units (apartments). Below is the HTML code for this component: <div *ngIf="$building | async as building"> ... <div *ngIf="$buildingUnit ...

Creating HTML elements with dynamic `routerLink` attributes in Angular 2

I have a model that references itself, as shown below. export class Entity { constructor(public id: number,public name: string,public children: Entity[]) { } } My goal is to create a tree list where each item has a routerlink. To achieve this, I ...

Adjusting Image Sizes in React using Material-UI: A Guide to Automatically Resizing Images for Various Screen Dimensions

Having trouble making images within my React project responsive across different screen sizes. Using Material-UI, I currently set the maxWidth property with a percentage value which doesn't give me the desired outcome. Seeking advice on a more dynamic ...

How do AppComponent and @Component relate to each other in AngularJs 2?

Recently, I came across the file app.component.ts in Example and found some interesting code. The link to the example is: here. Here's a snippet of the code: import { Component } from '@angular/core'; export class Hero { id: number; na ...

Python's for loop method can be used to find the second smallest number within a

I have designed this script to prompt the user to input a string of integers. Currently, my goal is to implement a loop that will determine the second smallest number in the list. Does anyone have advice on how I can accomplish this task? numbers_input ...

Creating a mechanism for automatic refreshing of JWT tokens in a Spring Boot and Angular application

I am working with Spring Boot and storing JWT tokens in httpOnly cookies. How can I implement automatic token refresh using the existing refresh tokens method on the backend? ...

How can I effectively make properties accessible in my template to facilitate form validation in Angular?

Scenario: I'm facing a situation in my Angular project where I have a LoginFormComponent. This component has a form with two properties: email and password. My goal is to create properties within this component that can be accessed in the template. Th ...

What is the best way to transmit a JSON object to a .NET server utilizing SignalR?

I am currently in the process of developing an Angular application that requires sending data from Angular forms to an external server using a .NET Core server and SignalR. While I have successfully established a connection between the Angular client and c ...

Utilizing Angular 2 for Displaying SVG Information

I am facing an issue with my angular application where I need to display product information in a SVG image obtained from a service in JSON format. Despite trying different methods, I have been unsuccessful in rendering the image on the HTML template. Att ...

Simulating HTTP requests in end-to-end Protractor tests for Angular 4 application

We are currently working on a large project and have developed numerous test cases to cover various real-life user scenarios in our end-to-end functional tests. During testing, our application makes multiple REST calls to complete the test cases. When exe ...