0

I need to paste some data in the DOM when a recursive ajax function ends its recursion.

The problem I have is that "$.when().done()" will trigger in the first step of rescursion but I need that it triggers on the last step of recursion, when recursion ends.

I really have no idea how to achive it, any help will be kindly apreciated!

function recursiveFunction(data) {

    // do something with data
    // and remove elements processed from data

    var param = {
            "data" : data
    };
    return $.ajax({
            data:  param,
            url:   'script.php',
            type:  'post',
            success:  function(response) {
                recursiveFunction(response);
            },
    });
}

$.when(recursiveFunction(data)).done(function(response){
    paintData();
});
user3287601
  • 21
  • 1
  • 4

3 Answers3

3

You can use deffered.promise object to handle recursive execution. I've modified your example to provide some data and stop condition. Example here -> jsfiddle

Damian Krawczyk
  • 2,241
  • 1
  • 18
  • 26
1

The key is to doing this concisely (and arguably simply) is :

  • to use an outer member for your data, rather than trying to pass it through

  • to build a .then() chain in the recursion, using the success path to recurse and the fail path for the terminal condition

  • to ensure that the php script will eventually return an HTTP error, thus avoiding infinite recursion.

Recursive function :

function recursiveFunction(response) {
    if(response) {
        // use `response` to act on the outer object `data`
    }
    return $.ajax({
        url:   'script.php',
        type:  'post',
        data:  {
            "data" : data
        }
    }).then(recursiveFunction);
}

Call as follows :

var data = {'whatever':'whatever'};//this is the outer member
recursiveFunction().fail(paintData);

No .when() and no messy counters.

See FIDDLE, which, for demonstration, uses a setTimeout in place of $.ajax() and an array as the outer member.

Beetroot-Beetroot
  • 18,022
  • 3
  • 37
  • 44
  • I need .when() because I'm waiting 2 deferred objects – user3287601 Feb 10 '14 at 01:45
  • 3
    No, `.when()` is for resolving two or more *parallel* promises. You have two *sequential* promises. Your second `.ajax()` is made after success of the first. – Beetroot-Beetroot Feb 10 '14 at 19:47
  • Excellent, I've been looking for a function that does just what you describe: _sequential_ Ajax calls. I'm searching a very large database (millions of rows) and found that I can improve UX and load times by chunking the request. This results in _N_ / _n_ (_N_: total number of rows, _n_:number of rows per chunk) ajax calls. If the calls would be sent in parallel, this would be the same as one request for _N_ rows---defeating the workaround. Thanks Beetroot-Beetroot! – seebiscuit Apr 11 '14 at 03:58
  • @Beetroot-Beetroot please see my [post](http://stackoverflow.com/q/23018273/2112866) about the problem I'm having implementing the above function. – seebiscuit Apr 11 '14 at 16:53
0

If you plan to use typescript you can do as below

    private updateDataNextLink(nextLinkAddress: string, outputAddress: string, defer?: JQueryDeferred<any>): JQueryPromise<string> {            
        if (defer){
            defer = $.Deferred();           
        }

        DataService.retrieveSkipTokenData1(nextLinkAddress).done((tagData) => {
            let tableData: any = ServiceContainer.officeApiHelper.createExcelTableFormat(tagData);
            ServiceContainer.officeApi.addData(outputAddress, [], tableData.rows).done((address) => {
                if (tagData['odata.nextLink']) {
                    ServiceContainer.officeApi.getOffsetCell(tableData.rows.length, 0, address).done((offsetAddress) => {
                        App.Instance.updateDataNextLink(tagData['odata.nextLink'], offsetAddress, defer);
                    });
                } else {
                    defer.resolve(address);
                };
            });
        });

        return defer.promise();
    }
shyam_
  • 2,370
  • 1
  • 27
  • 50