Синхронни ли са отложените обратни извиквания на 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+ спецификации. AFAIK, както 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, тъй като стеснява празнината за възможни странични ефекти и повторно влизане на метода. Забележка: Esailija, браво на 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. Което го прави SYNC, а не async. Или ако греша, моля, предоставете по-подробен кодов фрагмент, който наистина доказва, че е или асинхронен, или синхронизиран, тъй като горното изглежда 100% синхронизирано. - person ducin; 10.05.2017