Как jQuery имеет асинхронные функции?

Я удивлен, что не могу найти ясного ответа на этот вопрос. Итак, в jQuery вы можете сделать это:

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

Что, запустит анимацию fadeOut, но до того, как она закончит выполнение в течение 1 секунды, элементы будут удалены из DOM. Но как это возможно? Я продолжаю читать JavaScript, однопоточное (см. Также: Является ли JavaScript гарантированным однопоточным?). Я знаю, что могу сделать:

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

или даже лучше:

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

Я не понимаю, как работает JavaScript в одном потоке, но я могу использовать эти функции jQuery, которые выполняют асинхронно и заметно видят изменения DOM в разных местах одновременно. Как это работает? Этот вопрос не задан: "Как это исправить".

Ответ 1

jQuery анимации (и почти все анимации на основе javascript) используют таймеры для запуска анимации. Вызов .fadeOut() просто ЗАПУСКАЕТ анимацию и не завершается до тех пор, пока не будет выполнена серия операций таймера.

Это все еще однопоточное. .fadeOut() делает первый шаг анимации, он устанавливает таймер для следующего шага, а затем остальная часть вашего javascript (включая .remove()) запускается до завершения. Когда этот поток javascript заканчивается и время истекает для таймера, срабатывает таймер, и происходит следующий шаг анимации. Наконец, когда все этапы анимации завершены, jQuery вызывает функцию завершения анимации. Это обратный вызов, который позволяет вам что-то делать, когда анимация выполнена.

Вот как вы исправляете эту проблему:

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

Вы используете функцию завершения анимации и только удаляете элемент, когда анимация выполнена.

Ответ 2

В jQuery есть обработчик setInterval, который выполняет преобразования во всех зарегистрированных свойствах анимации. Если вы пришли из as3, подумайте об этом как обработчике EnterFrame или о методе Draw в OpenGL

Ответ 3

Вы можете использовать delay(), чтобы подождать определенное время или использовать обратный вызов для анимации, изменив fadeOut на animate. jQuery использует setTimeout для анимации и очередей.

Ответ 4

Точно так же, как 20 лет назад операционные системы выполняли многозадачность. Не было нитей, был только список вещей, которые нуждались в внимании и контроллер, который будет уделять внимание вещам, основанным на списке.

Один поток просто перебирает через список многократно все те вещи, которые требуют обслуживания. Единственное отличие здесь в том, что некоторые вещи связаны с периодом ожидания. Они находятся в списке, но помечены для обслуживания только через определенный период. Это очень простая реализация планировщика. Ядро на компьютере делает то же самое. Ваш процессор может выполнять только несколько программ одновременно, и даже тогда, только несколько. Ядро операционной системы должно решить, кто обращает внимание на миллисекунду на миллисекунду (см. Jiffies). Javascript "ядро" или среда выполнения делают то же самое, но, по сути, он работает на процессоре с одним ядром.

Это не говорит о таких вещах, как очереди прерываний и о том, с чем может справиться процессор, и я не уверен, что Javascript имеет какой-либо аналог, но на простом уровне я считаю это справедливым.

Ответ 5

Single Threading не имеет ничего общего с асинхронным программированием. http://social.msdn.microsoft.com/Forums/uk/csharplanguage/thread/3de8670c-49ca-400f-a1dc-ce3a3619357d

Если у вас есть только один поток, на котором вы можете выполнять инструкции, он не будет/всегда/будет выполняться. Во время этих пустых мест эта возможность для большей работы. Асинхронное программирование просто разбивает работу на блоки, способные к повторному вводу, и поток перескакивает туда, где это необходимо. (Концептуальное объяснение)

В этом случае ваш вопрос может быть более правильным: почему это не блокирующий вызов? В этом случае ответ довольно ясен, чтобы он отделял анимацию пользовательского интерфейса от вызовов данных. Вся среда JS не должна блокироваться в течение 1 секунды, а небольшие фрагменты оживляют элемент, который он может извлекать или преобразовывать данные, оживлять анимацию для других элементов и т.д.