Issue encountered with asynchronous waiting while invoking a function

var value = await this.upload();
if (value == true) {
  // Update item properties
  this.item.photos = this.uploaded;
  this.item.price = null;
  this.item.qty = null;
  
  // Add item to data service
  this.dataSrv.addItem(this.item)
    .then(() => {
      this.dataSrv.stopLoading();
      this.dataSrv.toast('Item Added Successfully');
      
      // Reset item and picture arrays
      this.item = {} as Item;
      this.pictures = ['', '', '', ''];
      this.uploaded = [];
      this.photos = ['', '', '', ''];
    })
    .catch(err => {
      this.dataSrv.stopLoading();
      this.dataSrv.toast('Error While Adding Item. Try Again Later');
      console.log(err);
    });
}

The above code snippet demonstrates the process of uploading images to Google storage using the upload function. However, there seems to be an issue where the execution does not wait for the images to be uploaded before proceeding with the true condition.

async upload(image?) {
  var counter = 0;
  this.pictures.forEach(i => {
    if (i != '') {
      let temp: string = (i) as string;
      // Process base64 image data
      temp = temp.replace("data:image/jpg;base64, ", '');
      temp = temp.replace("data:image/jpg;base64,", '');
      temp = temp.replace('must use [property]=binding:', '');
      temp = temp.replace('SafeValue', '');
      temp = temp.replace('(see https://g.co/ng/security#xss)', '');
      
      // Generate random ID for image
      const randomId = Math.random().toString(36) + Math.random().toString(36) + Math.random().toString(36) + Math.random().toString(36);
      
      // Upload image to storage
      const uploadTask = this.storage.ref('items/').child(randomId).putString(temp, 'base64', {
        contentType: 'image/png'
      });
      uploadTask
        .then(response => {
          console.log("uploaded");
          console.log(response);
          
          // Get download URL for uploaded image
          this.storage.ref('items/' + randomId).getDownloadURL().subscribe(url => {
            // Add URL to uploaded array
            this.uploaded.push(url);
            counter++;
          });
        })
        .catch(err => {
          console.log('not uploaded');
        });
    }
  });
  
  // Check if all images have been successfully uploaded
  if (counter != this.uploaded.length) {
    return false;
  } else {
    return true;
  }
}

Attempts to resolve the issue by using Promise return type in the upload function or adding a then after the function call did not yield any changes. The pictures array contains base64 image data.

Answer №1

Asynchronous functions do not inherently block execution. The challenge arises when a synchronous forEach loop is used, containing code that executes asynchronously.

An effective solution to this dilemma:

async upload(image) {
  // Implement .map instead of .forEach
  // Each callback function returns a Promise, resulting in an array of promises
  const promises = this.pictures.map(i => {
    // Insert your logic here
    // Remember to return the promise
    return uploadTask
        .then(response => { /* ... */ })
        .catch(() => { /* ... */ });
  })

  // Ensure all promises are resolved before proceeding.
  // Note: Promise.all will reject if any promise fails.
  // Your current code appears to address this by handling failed Promises within `.catch`.
  await Promise.all(promises);

  // At this point, the counter should reflect accurate counts
}

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

The controller in Angular uses the $scope symbol _

App.controller('todoController', function ($scope) { // create a message to display in our view $scope.todos = [{ name: 'angular', done: false }]; $scope.clearTodo = function () { $scope.todos = _.filter($scope.tod ...

Launching a new tab with a specific URL using React

I'm attempting to create a function that opens a new tab with the URL stored in item.url. The issue is, the item.url property is provided by the client, not by me. Therefore, I can't guarantee whether it begins with https:// or http://. For insta ...

Executing an external function on an element as soon as it is created in AngularJS: tips and tricks

I am looking to implement a function from an external library that will be executed on each item as it is created in AngularJS. How can I achieve this? Here is the code snippet of my application. var app = angular.module('app', []); app.contr ...

Error: Disappearing textarea textContent in HTML/TS occurs when creating a new textarea or clicking a button

I've encountered an issue with my HTML page that consists of several textareas. I have a function in place to dynamically add additional textareas using document.getElementById("textAreas").innerHTML += '<textarea class="textArea"></text ...

Uploading a file using AngularJs

When it comes to uploading an image or file using HTML tag in AngularJS, it seems that the tag is not supported. The solution? Create a custom directive. In my index.html page, I included the following code: <body ng-controller="myController"> ...

Error message from Angular stating that the factory function is not recognized as a function within the Controller

I have encountered similar questions in the past, but they often involve missing injections, and I hope that is not the issue in my case. For my current app project, I am attempting to send a GET request to the server to retrieve a list of modules. Contr ...

The flag will never turn true; it's stuck in the false position

Currently, I am in the process of developing a custom hook to store data on a server. To mimic the server call, I have implemented a simple setTimeout function that changes the value of the data creation flag to true after 2 seconds. I have a specific fun ...

Unexpected issue with resolving a Typescript string enum from a string value

As I was working on my project, I had an enumeration set up like this export enum RootPage { HOME = <any>'HomePage', LOGIN = <any>'LoginPage', TEST01 = <any>'Test01Page', LAUNCHPAD = <any>&apos ...

What criteria does Angular use to determine if a promise has been fulfilled?

Recently, I've delved into the realm of Angular promises for fetching data from a web service. One intriguing aspect that has caught my interest is how Angular somehow has the capability to determine whether a "request" has been successfully fulfilled ...

AngularJS Text Size Adjuster

I've managed to change the font and font size separately for different texts, but now I want to apply both functions to one text. How can I achieve this? Below is my HTML code: <div ng-controller="StylesCtrl"> <select ng ...

The type definition file for '@wdio/globals/types' is nowhere to be found

I'm currently utilizing the webdriverio mocha framework with typescript. @wdio/cli": "^7.25.0" NodeJs v16.13.2 NPM V8.1.2 Encountering the following error in tsconfig.json JSON schema for the TypeScript compiler's configuration fi ...

Error: The Gravatar service is unable to retrieve the property 'get' from an undefined source

I have a basic app with just one controller. I'm trying to debug the output of the Gravatar.get() function in the console. However, I encounter an error saying: "TypeError: Cannot read property 'get' of undefined". I'm confused because ...

What is the best way to determine the amount of distinct elements in an array of objects based on a specific object property?

I am working with an array called orders. orders = [ {table_id: 3, food_id: 5}, {table_id: 4, food_id: 2}, {table_id: 1, food_id: 6}, {table_id: 3, food_id: 4}, {table_id: 4, food_id: 6}, ]; I am looking to create a function that can calculate ...

AngularJS directs users back to the default page when they come from an external source

I am currently implementing AngularJS with ADAL for authentication in my project. One feature of the web app is that when a support ticket is closed, an email is automatically sent to the client who submitted the ticket. This email contains a link that al ...

Combining multiple object properties in AngularJS for filtering

Within my controller, I currently have an object var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.names = [{"Name":"Alfreds Futterkiste","City":"Berlin","Country":"Germany"}, {"Name":"Ana Truji ...

Steps to prevent uib-timepicker from automatically adjusting time based on the Browser Timezone

Currently in my database, timestamps are stored in UTC format. On the frontend, I am implementing uib-timepicker for time editing and updating purposes. However, I do not want uib-timepicker to automatically convert the time from the server's timezone ...

Looping Angular Components are executed

I am currently developing an Angular application and encountering an issue with my navbar getting looped. The problem arises when I navigate to the /home route, causing the navbar.component.html components to duplicate and appear stacked on top of each oth ...

Is there a way to remove a post with AngularJS and Express?

In my post.serv.js file, I have a code snippet for the function "delete" in my controller. "use strict"; app.factory('JnttPost', function ($resource) { var PostResource = $resource('/api/post/:_id', { _id: "@id" }, { ...

Using AngularJS and Rails, the GET request is triggered instead of rendering the template with ngModal

I am currently working with Rails, the angular-rails-templates gem, Angular 1.4.8, and using . In my project structure, I keep my template files in app/assets/javascripts/templates and my Angular project in app/assets/javascripts/angular-app. The setup fo ...

The callback for closing the $uibModal with a value will consistently result in undefined

Using ng-click="$widget.addItem()" in my template triggers a $uibModal. Everything is functioning properly - opening, closing, etc. The issue arises when trying to get the callback value from $modal.close($value). The function itself works correctly, the ...