tl; dr - Когда вы возвращаете отложенный (d2
) из обратного вызова (fd
), он вставляется в цепочку обратного вызова любого отложенного (d1
), называемого fd
,Это делается путем добавления продолжения цепочки обратных вызовов d1
в качестве обратного вызова на d2
, поэтому, если вы добавите обратный вызов к d2
после срабатывания d1
, он будет привязан к после продолжения d1
.
Я думаю, что вам не хватает того факта, что отложенные функции не являются асинхронными сами по себе, они просто более структурированыспособ цепочки обратных вызовов и обработчиков ошибок в асинхронном коде.Обратные вызовы не вызываются в неуказанное позднее время, они называются , когда запускается отложенный .Если вы хотите, чтобы это было позже, вам нужно интегрировать ваши звонки с reactor
.
Так что, возможно, это делает ответ на этот вопрос немного более очевидным:
Я не понимаю, почему время срабатывания отсрочек должно влиять на порядок выполнения обратного вызова.
Это произойдет, если вы измените обратные вызовы после , и вы запустите отложенное.
Объяснение вашего кода
В первом примере:
d1.callback(None)
вызывает запуск d1
f1
вызывается (печатает "f1") fd
вызывается (возвращает d2
)
Теперь все останавливается, потому что d2
было вставлено в цепочку обратных вызовов для d1
между f1
и f3
, но еще не было произведено.Тогда ...
d2.callback(None)
заставляет d2
быть запущенным f2
вызывается (печатает "f2") d1
's обратная связь возобновляется;поэтому f3
вызывается (печатает "f3")
Во втором примере
d1.callback(None)
вызывает запуск d1
f1
вызывается (печатает "f1") fd
вызывается (возвращает d2
)
Здесь d2
снова вставляется в цепочку обратного вызова.Это делается путем добавления продолжения текущей цепочки обратных вызовов в качестве обратного вызова к d2
.Поэтому, даже если вы явно добавили f2
в качестве обратного вызова для d2
, он добавляется после продолжения цепочки обратных вызовов d1
.Следовательно ...
d2.callback(None)
вызывает увольнение d2
;это приводит к продолжению цепочки обратного вызова d1
, начиная с ... f3
вызывается (печатает "f3") d2
следующий обратный вызов в это цепочка f2
, поэтому ... f2
называется (печатает "f2")