2

Is jQuery's each() function non-blocking?

In the below example, I expect "test in each" to be logged first, but in each test "test out of each" is logged first.

So this is causing the loop to run up to the body (sometimes the document) element before returning an error.

I'm just trying to get a common parent to wrap or if the two elements (firstp and lastp) are the siblings, then wrap those.

But, I'm mostly curious about the performance of the each() function and whether it is non-blocking.

while(firstp[0] !== lastp[0]){
        //If parents are siblings, this will do for wrapping.
        var isS = false;
            firstp.siblings().each( function(index, el){
                console.log("test in each");
                if(jQuery(el)[0] === lastp[0]){
                    isS = true;
                    return true;
                }
            });
            console.log("test out of each");
        if(isS === true){ break; }
        firstp = firstp.parent();
        lastp = lastp.parent();
    }

EDIT:

Sorry guys. This was a false alarm. Paul is correct. My HTML actually had two elements that was matching for firstp. I didn't realize this, so the first one did not have a sibling, causing the error. I was looking at the second element the whole time.

But, I did learn something in the process, so thanks for taking the time to answer.

3
  • When "test out of each" is logged do you also see "test in each" logged in the console? Commented Aug 2, 2011 at 2:18
  • @Shankar Yes, both texts are logged, just not in the order I would expect. Perhaps I'm missing something obvious. Commented Aug 2, 2011 at 2:21
  • @Senica: I don't think that you can make assertions about "order" when your console log messages don't demonstrate any evident relationship in their text. Messages could be printed from different iterations in the outer loop and you'd never know. Commented Aug 2, 2011 at 2:22

4 Answers 4

3

.each() is synchronous. My guess is this:

On the first iteration of your while loop firstp has no siblings so the object being iterated by each is empty and "test out of each" is the first thing logged. Then on the second iteration firstp has siblings so it enters the each and you immediately see "test in each" being printed after "test out of each".

I think you will see the proper behavior from console if you change your code to something like this, so you can see what iteration the loops are on:

var i = 1;
while(firstp[0] !== lastp[0]){
        //If parents are siblings, this will do for wrapping.

        var isS = false;
            firstp.siblings().each( function(index, el){
                console.log(i+": test in each ("+index+")");
                if(jQuery(el)[0] === lastp[0]){
                    isS = true;
                    return true;
                }
            });
            console.log(i+": test out of each"));
            i++;
        if(isS === true){ break; }
        firstp = firstp.parent();
        lastp = lastp.parent();
}
Sign up to request clarification or add additional context in comments.

1 Comment

Sorry guys. This was a false alarm. Paul is correct. My HTML actually had two elements that was matching for firstp. I didn't realize this, so the first one did no have a sibling. I was looking at the second element the whole time.
3

What do you mean by "non-blocking" here? Javascript typically runs in a single thread so... everything is blocking. (XMLHttpRequests are handed off to separate parts of the browser and, as such, don't count.) Event/animation queues change that slightly (in that callback invocations are decoupled from the user-specified statement order), but neither are in effect here.

If you are asking whether it runs asynchronously such that all the selected elements are not necessarily handled before the code following the each() call is invoked, then the answer should be "no".

That doesn't explain the results you're seeing, though. I'd suggest that perhaps, since you have nested loops, you may be interpreting the console log entries incorrectly. I suggest adding an iterating counter to the console log messages.

Comments

1

I think when the while loop begins firstp.siblings() is empty and it logs "test out of each" and then firstP is set to firstp.parent(); which might give some results so the inner message is logged. Please debug and see what do you get in the first iteration

Comments

1

When you do return true, do you mean to break out of the each iteration? If so, I believe that's supposed to be return false. I believe return true serves no effect.

Furthermore, you can probably change your code to something like this:

while(firstp[0] !== lastp[0]){
    //If parents are siblings, this will do for wrapping.
    var isS = false;
        firstp.siblings().each( function(index, el){
            console.log("test in each");
            isS = jQuery(el)[0] === lastp[0];
            return isS;
        });
        console.log("test out of each");
    if(isS === true){ break; }
    firstp = firstp.parent();
    lastp = lastp.parent();
}

1 Comment

Heh, you are right, I didn't mean to return true there, I meant false.

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.