What determines the execution order of methods in jQuery chains?
HTML Code
<div id="foo">
<h1>foo</h1>
<p>Pellentesque habitant morbi tristique.</p>
</div>
<div id="bar">
<h1>bar</h1>
</div>
jQuery Code
$('#bar').click(function () {
$('#foo p').hide('slow').appendTo('#bar').show('slow');
})
Expected Result
When #bar is clicked
- hide the
p
element in#foo
开发者_Python百科
- append
p
to#bar
- show
p
which is now a child of#bar
Actual Result
- append
p
to#bar
- hide the
p
element in#foo
- show
p
which is now a child of#bar
Questions
- What determines the execution order of methods in jQuery chains?
- How can I ensure that each event completes before the next starts?
To ensure you execute something AFTER an effect like hide or show, use a callback. http://docs.jquery.com/Effects/show#speedcallback
To Add:
Vincent is right, the execution is actually
- start hiding the p element in #foo (SLOWLY)
- append p to #bar (in a snap)
- start showing p which is now a child of #bar (SLOWLY)
What you saw was the result of the effect
- append p to #bar (executed)
- hide the p element in #foo (COMPLETED)
- show p which is now a child of #bar (COMPLETED)
The expected result is correct. The observed behaviour may be a result of hide('slow') which runs asynchronously. So it runs while the next action executes. So it appears as if p is appended to #bar first. You can try hide() without the slow to see if that makes a difference.
If you want to wait until each animation completes before doing the next step, use the animation callbacks detailed in the documentation:
$('#bar').click(function () {
$('#foo p').hide('slow', function(){
$(this).appendTo('#bar').show('slow');
});
});
show()
and hide()
are actually animation effects but when no arguments are passed they use an "instant" duration. However, due to the fact that they're implemented as animations, that means that they don't execute synchronously with the function chain. Thus, what you really should be using is a callback off of the hide()
call to trigger a callback function which calls append()
and then show()
.
http://docs.jquery.com/Effects/show
http://docs.jquery.com/Effects/hide
Hide is asynchronous. If you want to wait for it to finish, you need to put all the code you want to run after it into a callback function that you pass to hide as a parameter.
Pretty sure it's executed in the order you invoke it, it probably starts the hide part and a split second later it's appended to that other element but the animation part has already begun, it takes longer than a millisecond because you set it to 'slow' and it's jumping in opacity from 1 to 0, going from say 1 to .9 to .8 in milliseconds.
$.fn.hide = function() { alert('hiding'); return this; };
$.fn.appendTo = function() { alert('appending To') }
$('body').hide().appendTo('html')
You have to use callback if you want to queue the other methods run after the show hide thing like "Sixten Otto" has said. The animation of show hide will not wait for append method to execute. It starts a separate thread with setInterval while in the meantime, other code is invoked. So the result you got is not unexpected.
精彩评论