Executing Promises in a loop: TypeScript & Angular with IndexedDB

Currently, I am working on a data synchronization service where data is being retrieved from a web service and then stored in IndexedDB.

In my TypeScript Angular Service, the code looks something like this:

this.http
    .post(postUrl, postData)
    .success((data: any, status, headers, config) => {

         console.log("post success");
         console.log("results:");
         console.log(data);

         var records = data.Records;
         var promiseStack = [];

         for (var i = 0; i < records.length; i++) {

             var element = records[i];
             var key = this.dataService.getKeyFromElement(objectStoreConfig, element);

             console.log("key: " + key);

             this.dataService.keyExists(objectStoreConfig, key).then((update) => {

                 if(update){
                     // TODO: put
                     promiseStack.push(true);
                 } else {
                     console.log("using dataService to add to objectStore...");
                     console.log("adding: " + key);
                     this.dataService.add(element, objectStoreConfig).then((result) => {
                         promiseStack.push(result);
                     });
                 }
             });

         }

         this.q.all(promiseStack).then((result) => {
             console.log("done adding/updating all.");
             deferred.resolve(result);
         });
    })
    .error((data, status, headers, config) => {
    });

Upon running the code, I receive a post success message in the console, along with the keys of each record as expected. However, the issue lies in the asynchronous calls to the DataService. The problem arises specifically with the this.dataService.add function responsible for creating transactions and adding records to IndexedDB.

After examining the console output and the state of IndexedDB, it appears that only one record with a key value of 188 is added using this code sample. This demonstrates that the add function within DataService is called only for the last element in the records array.

Console Log:

post success
results:
Object
key: 78 
key: 194
key: 188
done adding/updating all. 
using dataService to add to objectStore...
adding: 188
using dataService to add to objectStore...
adding: 188
using dataService to add to objectStore...
adding: 188  

I'm currently exploring different ways to restructure my code so that the for loop allows each asynchronous call to be completed before proceeding to the next iteration. Any suggestions on how to achieve this?

Answer №1

Method 1 (specifically for ES6 compatibility)

If you are working with TypeScript 1.5, simply utilize let in place of var when defining your element and key variables:

let element = records[i];
let key = this.dataService.getKeyFromElement(objectStoreConfig, element);

The issue arises from the fact that element and key exist within the function's scope rather than the for loop, causing them to be overwritten each iteration. Using let places these variables within the for loop's scope.

Refer to What's-new-in-TypeScript for more information.

Method 2

Alternatively, employing Array.forEach instead of a traditional for loop can resolve the scoping issue:

records.forEach(function(element) {
    //...
});

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

Separating stylesheets, head, and other elements in a curl response

After successfully using curl to retrieve an external site, I noticed that the results were interfering with my own content. The CSS from the external site was affecting my webpage's layout and z-index values were conflicting. I am seeking a solution ...

I'm encountering an issue where the this.props object is undefined even though I've passed actions to mapDispatchToProps. What could

Summary: The issue I'm facing is that in the LoginForm component, this.props is showing as undefined even though I have passed actions in mapDispatchToProps. I've debugged by setting breakpoints in the connect function and confirmed that the act ...

Issues with Webpack and TypeScript CommonsChunkPlugin functionality not functioning as expected

Despite following various tutorials on setting up CommonsChunkPlugin, I am unable to get it to work. I have also gone through the existing posts related to this issue without any success. In my project, I have three TypeScript files that require the same ...

Using jQuery to extract a href URL from a div tag with jQuery

Is it possible to extract the href urls from anchor tags within a div tag? <div id="testing"> <a onclick="http://google.com">google</a> <a href="http://facebook.com">facebook</a> <a onclick="http://gmail.com">gmail< ...

Show the loader animation until the browser's loading icon stops spinning

My website receives a high volume of traffic and pulls data from several servers to display on the page. It typically takes 3-4 minutes for the entire page to finish loading. Here is a preview of some of the partial page data: I am looking to add a spinni ...

Determining if an item is located within a nested scroll container

How can one detect if a specific element within a scrollable container is currently visible to the user's view (i.e. within the visible area of the scrolling parent)? Is there a universal method available that does not require iterating through all p ...

Issue encountered: Trying to deploy firebase functions and hosting with vue-cli v3 and node.js leads to an error "No npm package found in functions source directory

My plan is to utilize Vue.js for the Frontend and Firebase Functions (Express.js) + Firestore for the Backend. Step 0: I initiated a new project on Google Firebase, then created a new Service Account with Owner's permissions to be used with Admin SDK ...

Is it possible for Angular.js to access a server session attribute?

I am in the process of creating an authentication system with angular.js My goal is to implement a session timeout after a period of inactivity and expire the current session if a user logs in from another device. In both scenarios - 1) idle timeout and ...

Adjusting the Depiction Camera Distortion in Three.js

In my top-down Three.js game, I'm currently using a Perspective Camera. However, I've noticed that it curves a bit too much because it's mainly for "first-person view". Is there a way to customize how objects bend or curve within the frustum ...

Adjust the position of an image to move it closer to the top using CSS

I have a fiddle where I am trying to adjust the position of an image (keyboard) to match a specific design. https://i.sstatic.net/flqCH.png In my fiddle, the keyboard image is slightly lower than the desired position shown in the design. I am looking for ...

Retrieve the URL for the React component

I'm facing some challenges with React fundamentals :/ I have a piece of code that creates a table using JSON data: import React from 'react' import { DataTable } from 'react-data-components'; function createTable(data) { ...

What is the best method for retrieving key-value pairs from an object based on a specific string filter?

const obj = { "pi_diagram": null, "painting": null, "heat_treatment": null, "welding_procedure": null, "inspection_test": null, "pipecl_hadoop": null, "pipecl": null, "ludo_min_hado ...

Firebase authentication encountered an error due to a network request failure

Utilizing firebase Hosting to host my website, I am encountering a persistent error when attempting to login using email/password. This is the JavaScript code that I am using: window.onload = () => initApp(); //Initialize screen function initApp(){ ...

To dynamically switch the login button to a logout state based on certain conditions

Here is the snippet of my login form in the header HTML: <ul class="nav navbar-nav navbar-right" ng-controller="loginController"> <li class="dropdown"> <a href="" class="dropdown-toggle" data-toggle="dropdown" ng-show="$scope.lo ...

How can I integrate Apple remote support into a website with the use of Javascript?

One thing that I find interesting is the ability to use the Apple remote with Front Row, as well as other apps on Mac that support it. I'm curious about whether Web Apps could also be made compatible through Javascript. I have a concept for a TV-like ...

TypeScript encounters difficulty locating the div element

Recently attempted an Angular demo and encountered an error related to [ts] not being able to locate a div element. import { Component } from "@angular/core"; import { FormControl } from "@angular/forms"; @Component({ selector: "main", template: ' ...

What strategies can I use to address the issue of requiring a type before it has been defined?

Encountered an intriguing challenge. Here are the types I'm working with: export interface QuestionPrimative { question : string; id : string; name : string; formctrl? : string; formgrp? : string; lowEx ...

Is there a way to incorporate the "Handoff to Human" feature in a Microsoft Teams bot app by utilizing the Teams Toolkit? Can this functionality be implemented using TypeScript?

Can someone assist me with figuring out how to incorporate the "handoff conversation to human agent mechanism" in my project using TypeScript, Microsoft Bot Framework, and Teams Toolkit? ...

Even when only a handful of modules are utilized, Webpack still imports a significantly large existing chunk

Currently, I am working on enhancing the splitChunks configuration in a multi-page application that utilizes Webpack 5, with a PHP backend and a Vue frontend. To optimize the vendor file size, I have started customizing the test function of the vendor cac ...

Calculating the hour difference between two time stamps (HH:MM:SS a) using moment.js

I have two time without date var startTime="12:16:59 am"; var endTime="06:12:07 pm"; I need to calculate the total hours between the above times using a library like moment.js. If it's not achievable with moment.js, then please provide a solution u ...