An Array of objects is considered NULL if it does not contain any values before being iterated through

Working with Files in TypeScript (Angular 8) has led me to Encode the files in Base64 using the code below:

  private async convertToBase64(evidences: Array<EvidenceToDisplay>): Promise<Array<EvidenceToDownload>> {
    const results: Array<EvidenceToDownload> = [];
    for (const evidence of evidences) {
      const evidenceToDownload: EvidenceToDownload =  {
        base64: null,
        name: '',
        extension: '',
      };
      const reader = new FileReader();
      reader.onloadend = function() {
        evidenceToDownload.base64 = reader.result;
      };
      reader.readAsDataURL(evidence.file);
      evidenceToDownload.name = evidence.name;
      evidenceToDownload.extension = this.getExtensionFromName(evidence);
      results.push(evidenceToDownload);
    }

    return results;
  }

The result is then obtained in another method as shown below:

  public async downloadEvidences() {
            const zip = new JSZip();
            let consecutive = 1;
            const allEvidences: Array<EvidenceToDisplay> = this.mergeEvidenceArray(this.manualEvidences, this.mobilityEvidences);
            const evidencesToDownload: Array<EvidenceToDownload> = await this.convertToBase64(allEvidences);
            console.log(evidencesToDownload);
            for (let i = 0; i < evidencesToDownload.length; i++) {
              console.log(evidencesToDownload[i].base64);
              zip.file(EVIDENCE + DASH + consecutive + DOT + evidencesToDownload[i].extension, evidencesToDownload[i].base64,
                 { binary : true, base64: true, compression : 'DEFLATE' });
              consecutive++;
            }
            zip.generateAsync({type: 'blob'}).then(function(blob) {
              FileSaver.saveAs(blob, 'test' + DOT + ZIP);
            });
          }

After observing the logs from the console, it became clear that there was a discrepancy between the initial and subsequent results. The issue seems familiar to cases involving "array.forEach" compared to a standard loop. Any idea why this might be happening?

To address the problem, I switched to encoding the file in binary instead of base64, eliminating the need for a file reader. This change helped resolve the inconsistency in logging results.

  public async downloadEvidences() {
    const zip = new JSZip();
    let consecutive = 1;
    const allEvidences: Array<EvidenceToDisplay> = this.mergeEvidenceArray(this.manualEvidences, this.mobilityEvidences);
    for (let i = 0; i < allEvidences.length; i++) {
      const extension = this.getExtensionFromName(allEvidences[i]);
      const MIMEType = this.getMIMEtype(extension);
      const blob = new Blob([allEvidences[i].file], { type: MIMEType });
      zip.file(EVIDENCE + DASH + consecutive + DOT + extension, blob,
        { binary : true, compression : 'DEFLATE' });
     consecutive++;
    }
    zip.generateAsync({type: 'blob'}).then(function(blob) {
      FileSaver.saveAs(blob, 'test' + DOT + ZIP);
    });
  }

For additional insights, reading files asynchronously proved to be beneficial. Check out this resource:

Answer №1

If you want to tackle this issue, one solution is to create an array of promises within the convetTob64 function. Below, I have provided a sample implementation with your updated code.

async function base64Converter(evidences) {
  return Promise.all(evidences.map(evidence => new Promise((resolve, reject) => {
    const evidenceToConvert = {
      base64: null,
      name: '',
      extension: '',
    };
    const reader = new FileReader();
    reader.onloadend = function() {
      evidenceToConvert.base64 = reader.result;
      resolve(evidenceToConvert);
    };
    reader.readAsDataURL(evidence);

    evidenceToConvert.name = evidence.name;
    evidenceToConvert.extension = '.someExtension';
  })));
}

async function handleFileInputChange(event) {
  const evidencesArray = await base64Converter(Object.values(event.target.files));
  console.log(evidencesArray);

}
<input type="file" onchange="handleFileInputChange(event)" multiple />
<div id="message"></div>

Answer №2

One possible explanation for this occurrence is that the information is not fully loaded when the initial console.log statement is executed due to the asynchronous nature of reader.onloadend.

It is advisable to pause until the data has finished loading before exiting the function convertTob64().

Answer №3

Issue resolved! Grateful for those who took the time to read and assist me. I have now switched to reading the file in binary format instead of base64.

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

Transferring session id across various devices using PHP

Here's the scenario: I have two users accessing different pages on separate devices - one user is on page 1 and the other is on page 2. My goal is to implement PHP forms on page 1 that can dynamically change the content displayed on the second user& ...

Ensuring that EJS IF/ELSE statements are evaluated accurately

I am encountering an issue where my variable 'answer' is returning the string 'success' and displaying correctly in the view. However, the IF/ELSE statement always seems to evaluate to the ELSE condition and displays 'no' inst ...

Unable to retrieve values using any = {} in TypeScript Angular 8

import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { enableProdMode } from '@angular/core'; enableProdMode(); @Component({ selector: 'app-home', templat ...

Structuring a Javascript project with a focus on component-based architecture

If I am following a component-based architecture and defining each component as an ES6 module, I organize all components in a /components folder. This folder is further divided into subfolders for grouped components. /js /components - header - ...

Unable to retrieve req.body data, despite having body-parser enabled

I've been working on setting up my login functionality, but I'm running into an issue with accessing the req.body object. Initially, the post route wasn't triggering at all (no console.log output in terminal) and the request would eventuall ...

The function tokenNotExpired encounters an error when attempting to access the localStorage, as it

I am looking to incorporate the angular2-jwt library into my project: https://github.com/auth0/angular2-jwt However, I encountered an exception when attempting to call the tokenNotExpired function: Exception: Call to Node module failed with error: Refe ...

Is it possible to direct the user to a particular link upon swiping to unlock?

Hello everyone, I could use some assistance with this code. I am looking to redirect someone to a specific page when they swipe to unlock and automatically transfer them to another page when the swipe ends. Any help is greatly appreciated. Thank you! $ ...

What are the essential Angular 2 observables for me to utilize?

I have created a form input for conducting searches. Upon user input into the search bar, I want to trigger calls to two separate APIs simultaneously. Here is my current attempt: myInput: new FormControl(); listOne: Observable<string[]>; listTwo: Ob ...

Sharing React components in projects

Two of my upcoming projects will require sharing components such as headers, footers, and inputs. To facilitate this, I have moved these shared components into a separate repository, which has been working well so far. In the common repository, I have set ...

Searching for parameters wrongly triggering the id on a different route

Having recently delved into mongoose, I must apologize in advance for any misuse of terminology on my part. Below is the content of my routes file: const express = require('express'); const router = express.Router(); const passport = require(&a ...

What is the best way to distribute components between two NextJS projects?

Confused about the best way to share ReactJs components between two NextJs applications - one for e-commerce and the other for a manager portal. In the e-commerce app, there are various UI components that I want to reuse in the manager portal. Considering ...

Highlight main title in jQuery table of contents

I have successfully created an automatic Table of Contents, but now I need to make the top heading appear in bold font. jQuery(document).ready(function(){ var ToC = "<nav role='navigation' class='table-of-contents vNav'>" + ...

Iterate through a JavaScript grid and display the items

I am attempting to iterate through a JavaScript table, aiming to display the elements located between two selections made by the user. Here is an example of the table structure: if the user selects IDs 2 and 5, the loop should display rows 3 and 4. I trie ...

Extracting data from a web service and populating an OWC11 spreadsheet with 10,000 rows

Having an issue with the web service call taking too long to return. The ASP.NET page is taking over a minute to start loading. Currently, I am using C# Response.Write() to output the data to Javascript for insertion into OWC11 spreadsheet. I'm lookin ...

What is the best way to add values to a JavaScript object using jQuery or plain JavaScript?

I have an object here and I am looking to dynamically insert values into it. var mergTr={}; //object for(dd in dispID) { var dataID=displayObj[dispID[dd]]; if(dataObj[dataID]) { var flag=0; var v ...

Completing the final touches on my jQuery typing enhancement feature

Currently, I have a code snippet that creates <li> elements with specific dimensions and background images when a user presses a key. The corresponding CSS class is applied to the generated <li>, displaying a specific character on the screen. H ...

Methods for reloading the requirejs module

There are two modules: settingmap.js var settingMap = { scWidth : [4000, 6000, 8000], scHeight : [5000, 7000, 9000], bxWidth : [100, 90, 80], bxHeight : [100, 90, 80], totalTime : [50, 40, 30], level : [1, 2, 3], boxColor : [&a ...

Enhancing the functionality of the Audio/HTMLMediaElement JavaScript object

Is there a way to modify the Audio object in order to add a stop function? The usual method is as follows: Audio.prototype.stop = function() { this.pause(); this.currentTime = 0; } However, when trying to implement this within a Chrome Extension ...

Initiate a JavaScript confirmation dialog using server-side logic in ASP.NET

Does anyone know how to troubleshoot the issue with this code? I am trying to make it so that when btnOne is clicked and a is true, a confirm box pops up. If yes is selected, then it should execute the btnTwo method. Currently, the popup isn't appeari ...

How can I execute route-specific middleware in advance of param middleware in Express v4?

Let me share a unique situation in my routing setup where I need to trigger a middleware before the parameter middleware is executed: router.param('foo', function (req, res, next, param) { // Accessing the param value ... next() }) router ...