How does jQuery have asynchronous functions?

2020-08-10 08:28发布

问题:

I'm surprised I can't find a clear answer to this. So, in jQuery, you can do this:

$(someElements).fadeOut(1000);
$(someElements).remove();

Which, will start a fadeOut animation, but before it finishes executing in the 1 second duration, the elements are removed from the DOM. But how is this possible? I keep reading the JavaScript is single threaded (see also: Is JavaScript guaranteed to be single-threaded?). I know I can do either:

$(someElements).fadeOut(1000).promise().done(function() { 
    $(someElements).remove();
});

or even better:

$(someElements).fadeOut(1000, function() { 
    $(this).remove(); 
});

What I don't understand is how JavaScript runs in a "single thread" but I'm able to use these jQuery functions that execute asynchronously and visibly see the DOM change in different places at the same time. How does it work? This question is not: "How do I fix this".

回答1:

jQuery animations (and pretty much all javascript-based animations) use timers to run their animations. The call to .fadeOut() just STARTS the animation and it doesn't complete until some time later when a series of timer operations are done.

This is all still single-threaded. .fadeOut() does the first step of the animation, it sets a timer for the next step and then the rest of your javascript (including the .remove()) runs until completion. When that javascript thread finishes and the time elapses for the timer, the timer fires and the next step of the animation happens. Finally when all steps of the animation have completed, jQuery calls the completion function for the animation. That is a callback that allows you to do something when the animation is done.

That is how you fix this issue:

$(someElements).fadeOut(1000, function() {
    $(this).remove();
});

You use the animation completion function and only remove the item when the animation is done.



回答2:

There is a setInterval handler in jQuery that performs transformations on all registered animation properties. If you're coming from as3, think of it as an EnterFrame handler, or like a Draw method in OpenGL



回答3:

You ca use delay() to wait for a certain time or use a callback for the animation, changing the fadeOut with animate. jQuery uses setTimeout to animate and queues.



回答4:

In much the same way that operating systems 20 years ago did multi-tasking. There were no threads, there were just a list of things that needed attention and a controller that would give attention to things based on the list.

A single thread just iterates through the list over and over services all the things that need servicing. The only difference here is that some things have a wait period associated. They are in the list, but are flagged to service only after a certain period. It's a very basic scheduler implementation essentially. The kernel on a computer does the same thing. Your CPU can only execute a few programs concurrently, and even then, only somewhat. The operating system kernel has to decide who gets attention on a millisecond by millisecond basis (see jiffies). Javascript's "kernel" or runtime does the same thing, but essentially like it's running on a CPU with only one core.

This doesn't talk about things like interrupt queues and such which a CPU can cope with, and I'm not sure Javascript has any analogue, but at a simple level, I think it's a fair representation.



回答5:

Single Threading has nothing to do with Asynchronous programming. http://social.msdn.microsoft.com/Forums/uk/csharplanguage/thread/3de8670c-49ca-400f-a1dc-ce3a3619357d

If you have only one thread on which you can execute instructions, it won't /always/ be executing. During those empty spots, that's opportunity for more work. Asynchronous programming just breaks up the work into re-entry capable blocks and the thread jumps around to where it's needed. (Conceptual explanation)

In this case, your question might more appropriately be: Why isn't this a blocking call? In which case the answer is pretty clear that it's to separate the UI animations from data calls. The whole JS environment shouldn't block for 1 second while taking small slices to animate an element which it could be retrieving or transforming data, queuing up animation for other elements, etc.