3

I make an ajax call with getPropertyId function to get data. I use a callback to get results then I use them. My problem is that the second each loop is launched before the end of the first one even if I put it inside the function. Can I synchronize my code to launch the second loop after the end of the first one ? Thanks

Plugins.DataHelper.getPropertyId(PropertyID, function(data){
    //code using data retrived with getPropertyId function

    $.each(list, function(index,value){
    //code "A" containing asynchronous calls
    });
});

$.each(filtredList, function(index,value){
    //code "B"
});
7
  • why not wrap the code B each loop in a function and call it after the code A loop? Commented Dec 21, 2011 at 14:09
  • 1
    The only $.each() I know of is synchronous. Are you really sure that putting the second call to $.each() in the same function as the first one still results in asynchronous behavior? Commented Dec 21, 2011 at 14:10
  • it didn't work, it make the call before ending code A Commented Dec 21, 2011 at 14:13
  • Maybe code A calls asynchronous methods (such as animations, or further AJAX requests)? In that case, you will have to find a way to chain code B from the last asynchronous callback from code A. Commented Dec 21, 2011 at 14:15
  • Yes, I used console.log("code A") and console.log("code B") and it should display "code A" 50 times before the first "code B" but it doesn't work ! Commented Dec 21, 2011 at 14:17

5 Answers 5

1

This is the very nature of JavaScript - you should definitely get used to event-based programming to avoid similar problems in the future.

Basically something like that should work:

Plugins.DataHelper.getPropertyId(PropertyID, function(data){
    //code using data retrived with getPropertyId function

    $.each(list, function(index,value){
        //code "A"
    });
    $.each(filtredList, function(index,value){
        //code "B"
    });
});

unless you are making AJAX calls inside "code A". In this case you are out of luck and should probably change your "code A" to use synchronous calls (generally a bad idea) or rewrite your code to work based on events.

One idea is to determine how many elements you want to process, then call a callback after each item has been processed. This callback should check if all the items have been processed (by incrementing counter and comparing it with number of items that were to be processed - this mechanism is similar to how lock works). When the function determines all the items have been processed, it does some actions (otherwise it does not).

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

2 Comments

Actually I make Ajax calls inside "code A" and I need this calls to be inside the each loop so how can I arrange my code or change it to oblige the second loop to wait the first ?? I already work with event but where can I raise the event which will contain the second loop ?
@YoussefMAKNI: Puth the second loop within a function and store it (do not execute it now!). This function should check the value of the lock as I mentioned. Then, after processing each AJAX request asynchronically, you should change the value of the lock (within success handler) and then call the callback (being still in the success handler). Callback will check the value of the lock and eventually (after it determines on the basis of the lock, that all the requests have been processed) will execute the loop. Got it?
1

You really could create a syncronised (=blocking) request, but that is pretty bad browser behavior. Much better is to make callback functions work for you, so you need to "continue" the code when that first ajax call is finished( success/error ).

Plugins.DataHelper.getPropertyId(PropertyID, function(data){
    XHRobject.onreadystatechange = function() {
        if( XHRobject.readyState === 4 ) {
            $.each(list, function(index,value){
               //code "A"
            });
        }
    }
});

Note, that is a simplified example to demonstrate the principle. Since you tagged jQuery too, you can make this very georgous by invoking promise objects. Looks like

Plugins.DataHelper.getPropertyId(PropertyID, function(data){
    $.ajax({}).done(function() {
        $.each(list, function(index,value){
           //code "A"
        });
    });
});

Comments

1

You should be able to achieve this by moving the second 'each' call inside your callback function like so:

Plugins.DataHelper.getPropertyId(PropertyID, function(data){
  //code using data retrived with getPropertyId function

  $.each(list, function(index,value){
    //code "A"
  });

  $.each(filtredList, function(index,value){
    //code "B"
  });
});

Edit: Check out this article for more information: flow control in javascript

2 Comments

This is won't work because there is AJAX calls inside "code A"
If 'code A' is making an ajax call to build the filtered list you can merge the each blocks into a single one and perform 'code B' in the success handler.
0

The first each waits untill the ajax-call is completed.

In the meantime the script continues and does second each first.

Tried placing the second each right after the first each-loop.

Comments

0

You can use the traditional Lock Semantics

Plugins.DataHelper.lock = false;//release
Plugins.DataHelper.getPropertyId(PropertyID, function(data){
    //code using data retrived with getPropertyId function

    $.each(list, function(index,value){
      Plugins.DataHelper.lock = true;//acquire
      //code "A"
      Plugins.DataHelper.lock = false;//release
    });
});
while(Plugins.DataHelper.lock)
   continue;//wait until released
$.each(filtredList, function(index,value){
    //code "B"
});

OR you can append the next function to call after the finish callback of your ajax xhr.

var nextF = function(){};
Plugins.DataHelper.getPropertyId(PropertyID, function(data){
    //code using data retrived with getPropertyId function

    $.each(list, function(index,value){
      //code "A"
      nextF();
    });
});
nextF = function(){
$.each(filtredList, function(index,value){
    //code "B"
});
}//You need to pass the scope to the nextF function like nextF.call(scope) where scope is cached somewhere

2 Comments

Have you tested it? I have bad feeling it will freeze my browser or execute "code B" instantly, without waiting for the results..
Ya The first one will freeze unless the ajax call releases the lock. and no I'vent tested either of them. second one is not freezing.

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.