Являются ли отложенные обратные вызовы jquery синхронными, если отложенные уже разрешены?

Я предполагаю, что ответ да, но код не самый простой для расшифровки. А в документах говорится

Любые обратные вызовы, добавленные к объекту с помощью deferred.then(), deferred.always(), deferred.done() или deferred.fail(), ставятся в очередь для последующего выполнения. Вызов deferred.resolve() или deferred.resolveWith() переводит Deferred в разрешенное состояние и немедленно выполняет все установленные doneCallbacks.

Но это явно не распространяется на случай присоединения обратного вызова к уже разрешенному отложенному вызову.


person wheresrhys    schedule 25.03.2014    source источник


Ответы (1)


Если обещание уже разрешено/отклонено, новые обратные вызовы выполняются синхронно.

Из jQuery.deferred() документа:

Как только объект перешел в разрешенное или отклоненное состояние, он остается в этом состоянии. Обратные вызовы по-прежнему можно добавлять в разрешенные или отклоненные отложенные — они будут выполняться немедленно.

Демонстрация (Fiddle):

var def = jQuery.Deferred(),
    promise = def.promise();
console.log('before 1');
promise.done(function () {
    console.log('done 1');
});
console.log('after 1');
def.resolve();
console.log('before 2');
promise.done(function () {
    console.log('done 2');
});
console.log('after 2');

Выход:

до 1
после 1
сделано 1
до 2
сделано 2
после 2

person Arun P Johny    schedule 25.03.2014
comment
Однако обратите внимание, что это один из тех аспектов, где обещания jQuery не следуют обещаниям /A+ характеристики. Насколько я знаю, реализации Q и Bluebird гарантируют, что обратный вызов выполняется асинхронно (например, через setImmediate). - person noseratio; 25.03.2014
comment
@Noseratio - интересно. Я подумывал о переходе на Bluebird, но такое поведение фактически затруднило бы мне реализацию некоторых функций. - person wheresrhys; 25.03.2014
comment
@wheresrhys Я не понимаю, как наличие детерминированного порядка выполнения вместо случайного усложнило бы реализацию какой-либо функции. - person Esailija; 25.03.2014
comment
@wheresrhys bluebird на самом деле имеет сборку (соответственно называемую Zalgo), которая делает это. Ты действительно не хочешь этого делать. Это может сделать действительно интересные ошибки. - person Benjamin Gruenbaum; 25.03.2014
comment
Я согласен с @Esailija. Я предпочитаю асинхронное выполнение в соответствии со спецификациями Promises, поскольку оно сужает разрыв для возможных побочных эффектов и повторного входа в метод. На заметку: Эсаилия, молодец на Bluebird, я фанат :) - person noseratio; 26.03.2014
comment
@Esailijia - если обратный вызов является синхронным, гарантируется, что любой синхронный код, вызываемый впоследствии, не будет выполняться первым, тогда как если обратный вызов является асинхронным, то сначала будет выполняться другой код. Точный случай, о котором я думаю, долго объяснять, но с синхронным определенно проще; У меня есть доказательство работы концепции jquery, и для работы с всегда асинхронными обратными вызовами потребуется некоторый рефакторинг. Я не имею в виду, что стандартный асинхронный способ объективно сложнее для каждого случая. - person wheresrhys; 26.03.2014
comment
@wheresrhys Единственная разница в том, что вам гарантируется определенный порядок выполнения, тогда как с такими реализациями, как jQuery, порядок выполнения не гарантируется. Так что просто абсурдно говорить, что такая гарантия усложняет реализацию чего-либо. - person Esailija; 26.03.2014
comment
Рефакторинг @Esailija сложнее, чем отсутствие рефакторинга - person wheresrhys; 26.03.2014
comment
@wheresrhys Я читал, что писать рабочий код сложнее, чем оставаться со своим кодом в условиях гонки, которые работают только иногда. - person Benjamin Gruenbaum; 26.03.2014
comment
привет @wheresrhys, @Esailija, @Noseratio и все, эта тема старая, но все еще актуальная. Поправьте меня, если я ошибаюсь, но кажется, что jQuery ‹ 3 (тот, что с Zalgo) детерминирован - обратный вызов всегда вызывается СИНХРОННО. В приведенном выше фрагменте кода вы можете видеть, что done1 выполняется до части 2 (before2, done2, after2). Это не ожидание следующего поворота JS. Что делает его СИНХРОННЫМ, а не асинхронным. Или, если я ошибаюсь, предоставьте более подробный фрагмент кода, который действительно доказывает, что это либо асинхронность, либо синхронизация, поскольку приведенное выше выглядит как 100% синхронизация. - person ducin; 10.05.2017