1

lets say you have a scenario where you needed to create a .csv output in a page's textarea...

So I have 2 arrays which i loop nested within one another. The result of the nested loop is a query that is passed an ajax call... I need to append the result of the ajax call into the textarea.

My question is how do you get the results printed out in the order they are requested (basically the order in the queries array)

//example array to loop.
var outerQuery= ['A', 'B', 'C', 'D', 'E', 'F'];
var outerQueryLegth = outerQuery.length;
var innerQuery= ['1', '2', '3', '4', '5', '6'];
var innerQueryLegth = innerQuery.length;

//the textarea where im going to print the results in order later to open in excel as a .csv file
var $csvText= $('#some-text-area');

//outter loop
$.each(outerQuery, function(outerIndex, outer){
      //Print the row
      $csvText.append('Row' + outer +'\r\n\r\n');
      
      //Nested inner loop (that should execute in order regarless or the time of the api call)
      innerQuery.reduce(function(innerCallback, inner, innerIndex){
        return innerCallback.then(function(){
        	return GoogleAnalyticsAPI(inner).then(function(response){
            $csvText.append(response.column1 +',');
          });
        });//end inner callback
      },Promise.resolve());
});

function GoogleAnalyticsAPI(val) {
	return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({column1: val });
    }, Math.floor((Math.random() * 1000) + 1));
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<textarea id="some-text-area" rows="20" cols="30"></textarea>

As you can see the results in the snippet run pretty out of wack ideally they should print like this:

RowA
1,2,3,4,5,6
RowB
1,2,3,4,5,6
RowC
1,2,3,4,5,6
.
.
.

The innerQuery.reduce i got from Ajax API calls in loop need to be executed in order which really helped thanks @jfriend00

Thanks guys

1
  • FYI, your argument named innerCallback is not a callback at all. It's a promise and calling it a callback really obscures how your code works. Just like in the previous question, you are trying to iterate asynchronous things with a synchronous loop structure (in this case $.each(). You can't do that. Commented Jun 25, 2016 at 17:20

2 Answers 2

1

You can continue with the same logic you used on the inner .reduce() loop in this prior answer and apply that for the outer loop as well. In addition, you can do this synchronization with plain Javascript concepts.

The key to doing that is that the inner .reduce() loop from the prior answer returns a promise that is only resolved when all the chained async operations in the inner loop are done. You can use that promise to control and synchronize the outer loop like this:

//example array to loop.
var outerQuery= ['A', 'B', 'C', 'D', 'E', 'F'];
var innerQuery= ['1', '2', '3', '4', '5', '6'];

//the textarea where im going to print the results in order later to open in excel as a .csv file
var $csvText= $('#some-text-area');

//outer loop
outerQuery.reduce(function(outerP, outerItem) {
    return outerP.then(function() {
        //Print the row
        $csvText.append('Row' + outerItem +'\r\n');
        return innerQuery.reduce(function(innerP, inner, innerIndex){
            return innerP.then(function(){
                return GoogleAnalyticsAPI(inner).then(function(response){
                $csvText.append(response.column1 +',');
              });
            });
        }, Promise.resolve()).then(function() {
            $csvText.append('\r\n\r\n');
        });      
    });
}, Promise.resolve());

function GoogleAnalyticsAPI(val) {
	return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({column1: val });
    }, Math.floor((Math.random() * 500) + 1));
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<textarea id="some-text-area" rows="20" cols="30"></textarea>

Sign up to request clarification or add additional context in comments.

1 Comment

Thansk bro i actually tried this way after u helped me out twith the previous ones but where i got it all wrong was in the returns... I need to touch up on this... But really appreciate the help i managed to do what i needed now thanks to you...
1

You can use .queue(), .promise() to return functions in sequential order corresponding to index within an array

//example array to loop.
var outerQuery = ['A', 'B', 'C', 'D', 'E', 'F'];
var outerQueryLegth = outerQuery.length;
var innerQuery = ['1', '2', '3', '4', '5', '6'];
var innerQueryLegth = innerQuery.length;
var $csvText = $('#some-text-area');

// create `"outerQuery"` queue
$csvText.queue("outerQuery", $.map(outerQuery, function(outer, index) {
  return function(next) {
    $(this).append((index > 0 ? '\r\n\r\n' : "") 
                    + 'Row' + outer + '\r\n\r\n')
    // create `"innerQuery"` queue
    .queue("innerQueue", $.map(innerQuery, function(inner, innerIndex) {
        return function(_next) {
          return GoogleAnalyticsAPI(inner).then(function(response) {
            $csvText.append(response.column1 + ',');
            // call `_next` function in `"innerQueue"`
          }).then(_next); 
        }
      })).dequeue("innerQueue").promise("innerQueue")
    // call `next` function in `"outerQueue"`
    // when all functions in current `innerIndex`
    // of `innerQueue` array , `"innerQueue"` completes
    .then(next)
  }
})).dequeue("outerQuery");

function GoogleAnalyticsAPI(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({
        column1: val
      });
    }, Math.floor((Math.random() * 1000) + 1));
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<textarea id="some-text-area" rows="20" cols="30"></textarea>

1 Comment

Thanks mate! You are an ace!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.