Tips for preventing memory leaks when generating promises in a recursive manner

In the development of my Ionic application, I encountered a challenge regarding downloading data with pagination and inserting it into the database recursively. I am utilizing Angular's $q service to create promises for this purpose. The issue arises when executing the recursive function as although the data is successfully downloaded and inserted, the memory usage keeps increasing throughout the process. Even after the promise chain resolves entirely, the allocated memory remains in use.

Below is the snippet of my recursive function:

// offset:  last downloaded row count
// limit:   row count to download at each page
// numRows: row count to download at all
function dowloadAndInsert(offset, limit, numRows) {
    var deferred = $q.defer();

    // Recursion step: We do not reached at the end of data
    if((offset + limit) <= numRows) {

        // Download the data
        downloadData(offset, limit)
            .then(function(response) {

                // Insert the data
                insertData(response)
                    .then(function(insertTime) {

                        // Recursion step
                        dowloadAndInsert(offset + limit, limit, numRows)
                            .then(function() {
                                deferred.resolve();
                            })
                            .catch(function(reason) {
                                deferred.reject(reason);
                            });
                    })
                    .catch(function(reason) {
                        deferred.reject(reason);
                    });
            })
            .catch(function(reason) {
                deferred.reject(reason);
            });
    }

    // Base case: We reached at the end of data
    else {
        var remainingRows = numRows % limit;        // Means the last limit actually

        // If exists, insert remaining rows
        if(remainingRows !== 0) {

            // Download the last piece of data
            downloadData(offset, remainingRows)
                .then(function(response) {

                    // Insert the last piece of data
                    insertData(response)
                        .then(function(insertTime) {

                            // Base case, successfully downloaded and inserted everything
                            deferred.resolve();
                        })
                        .catch(function(reason) {
                            deferred.reject(reason);
                        });
                })
                .catch(function(reason) {
                    deferred.reject(reason);
                });
        }

        else {
            // Base case, successfully downloaded and inserted everything
            deferred.resolve();
        }
    }

    return deferred.promise;
}

Note: The response object obtained from the downloadData function consists of a substantial amount of data, sometimes exceeding 100,000 rows with 18 columns. As a result, the total memory usage can reach up to 1GB while testing on an iPad Air 2 device.

Considering the significant volume of data processed in my recursion function, my query regarding memory management presents a unique aspect compared to other inquiries about recursive memory leaks.

Thank you.

Answer №1

Your code is putting in excessive effort, using promise chaining unnecessarily. Instead of performing the deferred dance, you can simply chain promises together to resolve the issue and improve the quality of your code:

function dowloadAndInsert(offset, limit, numRows) {
  const start = offset,
        numFetch = ((offset + limit) <= numRows ? limit : numRows % limit;
  if(numFetch === 0) {
     return Promise.resolve(); // we're done;
  }
  return downloadData(start, end).
           then(insertData).
           then(downloadAndInsert.bind(null, offset + numFetch, limit, numRows);
}

This portion of code performs the following tasks:

  • Determines the number of rows needed to fetch and insert.
  • If there are no more rows to fetch, it returns an empty promise.
  • Otherwise, it fetches the necessary rows and continues fetching the remaining rows.

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

AngularJS dynamically style form fields on input focus

How can angularjs be used to format an input field value based on whether or not the input has focus? I need help with displaying numbers in an input field rounded to 2 decimal places, but switching to show the full value when the user clicks on the field ...

Issue with Vue.js: "Load more data" button functionality malfunctioning

I've been working on my Vue.js code and I'm trying to implement a "Show More" button for the data fetched from an API. Initially, only 10 items should be displayed, and when the button is clicked, it should load another 10 items and so on. I chec ...

CKEditor with Readonly Option and Active Toolbar Controls

In my current Rails project, I have successfully set up a CKEditor instance in readOnly mode. Everything is functioning as expected. Now, I am attempting to add a custom plugin button to the toolbar while keeping the textarea in readOnly mode. After some ...

Ways to delay the execution of a loop using setTimeout or setInterval

In my code, I have an array named RotatorNames which includes different elements. Let's say it currently includes ["rotatorA","rotatorB","rotatorC"]. My goal is to loop through this array and trigger a click event for each item. While I have made pro ...

Using jQuery: in the event that $(this) or a different element loses focus, then

I am looking to execute a function when either the currently active element $(this) or another specific element (e.g.: div#tooltip) loses focus. However, I have not been successful in finding the right approach. I have attempted the following: $(this).add ...

What is the method for obtaining a date in the format of 2018-05-23T23:00:00.000+00:00?

Recently, I've been attempting to filter data based on dates in my database. The format in which the dates are saved is as follows: 2018-05-23T23:00:00.000+00:00 This was my initial approach: router.get('/byDate', function (req, res) { ...

Tips for troubleshooting failed test steps in protractor

Need help debugging failed test steps in Protractor Here is an example of a test case: it('Testcase-TC_BY_09 , Case 2: User Selects NO option', function() { //Execution Steps Login();//Calling Login Function //options Click //book_ty ...

Numerous perspectives within an angular.js application

Issue I'm currently working on creating a product list with the following initial features: Server-side pagination Server-side filtering I am facing several challenges with my current setup, but the main issue is that I can't figure out how to ...

Maintaining Login State in Django REST API After Page Refresh

Struggling with maintaining login status when using DJANGO Rest API and an AngularJS client. Despite having authtoken and default auth classes set up, including 'rest_framework.authentication.TokenAuthentication' and 'rest_framework.authenti ...

What is the method for determining the numerical worth of the px containers?

https://i.stack.imgur.com/0K2TD.png Total width of the bar is set to 500px, with the red box at a width of 150px, the yellow box at 200px, and the green box at 50px. CSS Styles: .box { float:left; width:150px; box-shadow:3px 3p ...

Passing data between pages using React Native hooks

I am a newcomer to React Native and facing challenges in passing data to another page. Specifically, I want to transmit data from the QR Reader to another Page. Below is my code on the first screen: const LoginScreen = (props) => { const onSucce ...

Having Trouble Importing a Dependency in TypeScript

My experience with using node js and typescript is limited. I attempted to include the Paytm dependency by executing the following code: npm install paytmchecksum or by inserting the following code in package.json "dependencies": { ... & ...

Highcharts gauge removing unnecessary white borders

I have created a highchart gauge code that looks great on JSFiddle, but when I paste it into my website, the 'border' options (borderColor and borderWidth) don't seem to work. The browser automatically adds white borders to my series, toolti ...

carousel initialization failed due to materialization error

I am experiencing a peculiar issue with the carousel feature on a website built using MaterializeCSS. Sometimes it functions correctly, but other times I encounter the following error: jQuery.Deferred exception: c is undefined s@https://cdnjs.cloudflare.c ...

Another component's Angular event emitter is causing confusion with that of a different component

INTRODUCTION In my project, I have created two components: image-input-single and a test container. The image-input-single component is a "dumb" component that simplifies the process of selecting an image, compressing it, and retrieving its URL. The Type ...

Setting up CloudKitJS Server-to-Server Communication

I'm struggling to make this work. I keep encountering the following error message: [Error: No key provided to sign] Below is my configuration code: CloudKit.configure({ services: { fetch: fetch }, containers: [{ containerIdentifier: & ...

Error: The function "navigate" has not been declared or defined

Just starting out in reactjs and embarking on a new project. I've successfully implemented a register and login function using firebase, but hit a snag when trying to navigate to a new page like the dashboard upon user login, I encountered this error: ...

Checking for an exact value using the includes() method in JavaScript - a comprehensive guide

In order to populate checkboxes based on a string delimited with pipes, I have been using the includes() method. However, I am encountering an issue where items with similar names are both marked as true because they share the same string, even if they are ...

Struggling with State Management in React

I am utilizing an API (in Node) to make a call from my react component (Stats.js) The function getName is taking a prop that is passed in (known as 'value') so it can search for a value in MongoDB. See the code snippet below: /* Stats React Com ...

Determine a specific value in a JSON array of objects and retrieve a different value using Angular

Is there a way to search through my JSON data to locate two specific key values, for example weight = "8m" and meters = "7t", and then retrieve the name value of the object where these two values match, for instance "25t"? Here is a snippet from data.json ...