Executing a loop synchronously within an Angular application

I am grappling with Angular as I have an $http request retrieving multiple rows that need to be processed synchronously. The challenge arises when these records must be processed against a local SQLite database on an iOS device, which involves an asynchronous call.

If any of the records in the loop fail, I need to halt the entire operation and loop. Below is the code snippet:

var username = $rootScope.currentUser;
            window.logger.logIt("Executing incremental sync with username " + username);

            var url = $rootScope.serviceBaseUrl + 'SyncData/GetSyncItems?userid=' + username + '&lastSyncDate=' + lastSyncDate.toString();
            var encoded = encoder.encode($CONFIG.serviceAccount);

            $http.defaults.headers.common.Authorization = 'Basic ' + encoded;

            $http({ method: 'Get', url: url })
                .success(function(data, status, headers, config) {
                    var processes = [];

                    for (var i in data) {
                        var params = data[i].Params;
                        var paramsMassaged = params.replaceAll("[", "").replaceAll("]", "").replaceAll(", ", ",").replaceAll("'", "");
                        var paramsArray = paramsMassaged.split(",");
                        var process;

                        if (data[i].TableName === "Tabl1") {
                            window.logger.logIt("setting the process for a Table1 sync item");
                            process = $Table1_DBContext.ExecuteSyncItem(data[i].Query, paramsArray);
                        } else if (data[i].TableName === "Table2") {
                            window.logger.logIt("setting the process for an Table2 sync item");
                            process = $Table2_DBContext.ExecuteSyncItem(data[i].Query, paramsArray);
                        } else {
                            window.logger.logIt("This table is not included in the sync process. You have an outdated version of the application. Table: " + data[i].TableName);
                        }

                        window.logger.logIt("got to here...");

                        processes.push(process);
                    }

                    window.logger.logIt("Finished syncing all " + data.length + " records in the list...");

                    $q.all(processes)
                        .then(function (result) {
                            // Update the LastSyncDate here
                            $DBConfigurations_DBContext.UpdateLastSyncDate(data[i].CreatedDate);

                            alert("finished syncing all records");
                        }, function (result) {
                            alert("an error occurred.");
                        });
                })
                .error(function(data, status, headers, config) {
                    alert("An error occurred retrieving the items that need to be synced.");
                });

Table2's ExecuteSyncItem function:

ExecuteSyncItem: function (script, params) {
    //window.logger.logIt("In the Table2 ExecuteSyncItem function...");

    //$DBService.ExecuteQuery(script, params, null);

    var deferred = $q.defer();

    var data = $DBService.ExecuteQuery(script, params, null);

    if (data) {
        deferred.resolve(data);
    } else {
        deferred.reject(data);
    }

    return deferred.promise;
}

DB Service code:

ExecuteQuery: function (query, params, success) {
    $rootScope.db.transaction(function (tx) {
        tx.executeSql(query, params, success, onError);
    });
},

In response to Maxim's question "did you log process method," here's what I'm doing:

ExecuteSyncItem: function (script, params) {
    window.logger.logIt("In the Experiment ExecuteSyncItem function...");

    //$DBService.ExecuteQuery(script, params, null);

    var deferred = $q.defer();

    var data = $DBService.ExecuteQuery(script, params, function () { window.logger.logIt("successCallback"); });

    if (data) {
        window.logger.logIt("success");
        deferred.resolve(data);
    } else {
        window.logger.logIt("fail");
        deferred.reject(data);
    }

    return deferred.promise;
}

"data" is undefined every time. "fail" is logged along with "successCallback." Even though the executeQuery is working and updating the data as expected, it seems to be a matter of understanding promise syntax. Since ExecuteQuery is asynchronous, how should I handle deferred.resolve() and deferred.reject()?

Answer №1

You are heading in the right direction

I recommend utilizing $q.all

$q.all([async1(), async2() .....])

Aggregates multiple promises into a single promise that is fulfilled when all of the input promises are fulfilled.

Yields a single promise that will be fulfilled with an array/hash of values, each value corresponding to the promise at the same index/key in the promises array/hash. If any of the promises is fulfilled with a rejection, this resulting promise will be rejected with the same rejection value.

For instance:

var processes = [];

processes.push(Process1);
processes.push(Process2);
/* ... */

 $q.all(processes)
            .then(function(result)
            {    
              /* all aforementioned async calls have concluded */
 
              $scope.response_1 = result[0];
              $scope.response_2 = result[1]; 
             
            }, function (result) {
              alert("Error: No data returned");
            }); 

In your scenario, you iterate through a loop and invoke async methods (Process1, Process2) 10 times (8 and 2 respectively). To utilize $q.all, the Process1, Process2 must return a promise.

Thus, I would structure it in this manner:

var Process1 = function(stuff) {

    var deferred = $q.defer();

    var data = $DBService.ExecuteQuery(stuff.query); // This operation is asynchronous
 
    if (data) {
      deferred.resolve(data);
    } else {
      deferred.reject(data);
    }

    return deferred.promise;
}

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

Error: React.js - operationStore.getItems function is not defined

I've encountered an issue while running my Web App with the command: node --harmony gulpfile.babel The error message states: Uncaught TypeError: operationStore.getItems is not a function I'm struggling to identify the root cause of this problem ...

Having trouble with parsing JSON data using jQuery?

I am currently working on retrieving a result set using postcodes with jQuery autocomplete. However, the code I have implemented seems to be displaying an empty set of rows. <html lang="en"> <head> <meta charset="utf-8> <title>Ausp ...

Trigger an Angular controller within Foundation's reveal modal

Trying to implement a form using foundation's reveal modal, I want to incorporate an angular controller within the form for ajax form submission instead of the default post/refresh behavior. This is my primary view: <html lang="es" ng-app="crm"&g ...

Can you explain the process that takes place when require("http").Server() is called with an Express application passed in as a parameter?

As I was exploring the Socket.io Chat Demo found at this link: http://socket.io/get-started/chat/, I came across their require statements which left me feeling confused. var app = require('express')(); var http = require('http').Server ...

Encountering a 500 Internal Server Error message while attempting to access a WebMethod through ajax

I'm encountering an issue with accessing my C# WebMethod in the code behind, resulting in a 500 internal server error. I cannot figure out why it's not working, so any assistance in identifying the problem would be highly appreciated. https://i. ...

Learn how to remove data from a React JS application without causing a page refresh by utilizing the useLoaderData() function in conjunction with React Router

I am working on preventing my table from refreshing with the new version of userLoadData from react-router-dom@6 after deleting some data. In an attempt to achieve this, I created a function called products() within useLoaderData. While this function succ ...

Different body background color changes every second

I have a function called makeRandColor that generates a random color using RGB and template string literals. However, I am struggling to figure out how to make it work every second. I tried using setInterval but it doesn't seem to be functioning prope ...

Utilizing Selenium WebDriver with Python: Harnessing Test-Created Variables in JavaScript

How can I trigger the variable a, which I set to "Text" for testing purposes? ...

The issue with executing event.keyCode == 13 in Firefox remains unresolved

I've implemented a function that sends comments only when the "enter" key is pressed, but not when it's combined with the "shift" key: $(msg).keypress(function (e) { if (event.keyCode == 13 && event.shiftKey) { event.stopProp ...

Create a JavaScript variable every few seconds and generate a JSON array of the variable whenever it is updated

My variable, which consists of random numbers generated by mathrandom every second, such as "14323121", needs to be saved to an array for the latest 10 updates. function EveryOneSec() { var numbers = Math.random(); // I want to create an array from th ...

Clicking a button will bring back the component to its assigned ID

How can I dynamically add a component <SaveTask/> to a specific div tag with the id of <div id="saveTask">? When I use this.setState(), it replaces the container and displays only the <SaveTask/> component. However, I want to re ...

Ensuring the Correctness of URLs Using Javascript

I have a client-side URL validation code that I am currently using. I am wondering if there is a more efficient way to achieve the same result. My question pertains to the overall approach rather than the specific regex. this.validators.myUrl = function ...

javascript - audio is not working on the web

I've been trying to incorporate sound into my website using this code. Strangely, the sounds only seem to play in Adobe Dreamweaver and not in any browsers. Any advice would be greatly appreciated! :) var audio1 = new Audio('sound1.mp3'); v ...

AngularJS enables you to easily manipulate image width and height using the ng-file-upload feature

Seeking assistance with validating image width and height based on a 1:3 ratio prior to uploading using ng-file-upload. The validation should occur before sending the image to the server. Unsure how to retrieve the dimensions of the selected image for val ...

Incorporating filters within ui-sref for enhanced functionality

After coming across this answer, I realized it doesn't address my specific issue. My goal is to have the complete state name generated by my filter, rather than just using the filter for state parameters. Is there a way to use a filter to generate th ...

The attribute selector specifically targets the number 3, excluding numbers such as 13 or 23 from being selected

Within a form, there is a segment that displays groups of 4 weeks in each division. Take a look at the code snippet provided below <div class="form-check" data-weeknr="1,2,3,4"></div> <div class="form-check" dat ...

What's the best way to add a timestamp and class name to Angular's $log for an enhanced logging experience?

Is there a way to customize Angular logs by adding a timestamp and classname? For example: $log.info('this log entry came from FooBar'); "9:37:18 pm, FooBar: this log entry came from FooBar" I've come across various examples online that ...

Unable to click, but can only be activated by touchstart or mousedown

Is it possible to bind a 'click' event to a paragraph? Here is the function I am using: $(document).on('touchstart mousedown',"p span.text", function(e) { console.log('I was clicked'); *more code here* }); When I ...

Selecting the events that I want my directives to track

Here is a directive example: 'use strict'; angular.module('epw') .directive('md-title', function ($rootScope) { return { scope: { listenTo: '@' }, controller: function () { $ ...

Code to achieve smooth scrolling from a hyperlink to a specific div element

<div style="border-radius: 10px; border: 2px solid #a1a1a1; padding: 10px 20px; width: 94%;"> <ul> <li>Listing of course details by country <ul> <li><a href="#bdpindia">India</a></li> <li><a href="#b ...