haz
haz

Reputation: 780

jquery waiting for .ajax() to complete within .each() iteration

Ive a jquery function that obtains text from all nodes of a particular class using the jquery .each() selector:

function get_text()
            {
              $(".my_class").each(function () 
              {
                $this = $(this);
                node_text = $this.text();
                console.log(node_text);
              })
            }

That works as expected. Next, I want to send the text to a php script using .ajax() :

function get_php_text(node_text)
            {
               let url = `myphp.php?string_text=${node_text}`;
                 $.ajax(
                      {
                        url: url,
                        success: function(result)
                          { 
                            console.log(result);
                          }
                      });
            }            

That function also works as expected.

When I run the following:

function get_text()
            {
              $(".my_class").each(function () 
              {
                $this = $(this);
                node_text = $this.text();
                get_php_text(node_text);
              })
            }  

I run into a problem as get_php_text() is not waiting for each .each() iteration to complete.

How can I rewrite the get_text() function so that it waits for the get_php_text() to return before going to the next iteration?

Upvotes: 1

Views: 269

Answers (2)

Adrian
Adrian

Reputation: 8597

Edit: Removed a promise as pointed out $.each doesn't support it.

Another example is using closures, but it should be used if you want to send data every time an iteration occurs in $.each.

function get_text() {
    function SampleClosure(node_text) {
        let url = `myphp.php?string_text=${node_text}`;
        $.ajax({
            url: url,
            success: function(result) {
                console.log(result);
            }
        });
    }

    $(".my_class").each(function() {
        $this = $(this);
        node_text = $this.text();
        SampleClosure(node_text);
    })
}

So, what happens above is, every element, the text is extracted and passed to a Closure which is an expression that can reference variables within its scope when it was first declared. So even if you change the passed variable before the Ajax call is sent, it'll still use the old passed text and function will execute. I like to (which is wrong) think of it as creating an instance of a function with passed data which once completed is taken care of by GC, and within the loop, multiple instances of the function are created within their own memory allocation. As I said, this is how I see it, and what I said might be wrong, but theoretically this is how the process appears to me and works.

Upvotes: 2

vi5ion
vi5ion

Reputation: 1028

You can make it so that the iterating is done inside the success handler of your ajax call, by making get_php_text() recursive. This way the next iteration will only occur after the previous one has finished its ajax request.

function get_text() {
  let node_text_array = [];
  $(".my_class").each(function() {
    node_text_array.push($(this).text());
  });
  get_php_text(node_text_array);
}  

function get_php_text(node_text_array) {
  if (node_text_array.length>0) {
    let node_text = node_text_array.splice(0,1);
    let url = 'myphp.php?string_text=${node_text}';
    $.ajax({
      url: url,
      success: function(result) {
        console.log(result);
        get_php_text(node_text_array);
      }
    });
  }
}

Upvotes: 2

Related Questions