You cannot call .remove()
right away, because the .fadeOut()
operation is an asynchronous operation that returns immediately (after the animation starts), but continues execution through timers. When .fadeOut()
returns and the next chained operation is performed, the animation is just beginning - it is not yet complete. If you execute .remove()
with a normal chain, you delete it right away until the animation makes any progress.
So, as you have discovered, you need to wait until the completion callback is called for the animation, and then you can delete it.
The only exception is additional chaining animation calls. You can link an animation because animation is a special case that enters the animation queue. After the animation starts, subsequent calls to the animation indicate that the animation is already in progress and that they are in the internal queue. When the first animation ends, it checks the animation queue to see if there is more animation with the chain.
Almost all asynchronous operations in javascript are not blocked like this. This means that calling them to launch is simply a call to launch them. Then this call returns immediately, and the rest of the operation is executed through timers or other events, and subsequent javascript continues to be executed (including other chain methods). You will only know when the operation is actually performed by registering for the completion callback.
The same is true for ajax operations, image loading, etc.
You made me think about how to make the .remove()
method work through the animation queue. You can actually do this by creating a new version of remove () as follows:
$.fn.fxRemove = function() { this.queue(function(next) { $(this).remove(); next(); }); return(this); }
This form of deletion enters the animation queue and will be executed when the animations are constrained before its completion. So you can use:
$(this).parent().fadeOut(500).fxRemove();
There is a working example here: http://jsfiddle.net/jfriend00/3Hg6G/