Я читал об отсрочках и обещаниях jQuery и не вижу разницы между использованием .then()
& .done()
для успешных обратных вызовов. Я знаю, что Эрик Хиндс упоминает об этом .done()
и .success()
сопоставляет с той же функциональностью, но я предполагаю, что так и происходит, .then()
поскольку все обратные вызовы вызываются при завершении успешной операции.
Может кто-нибудь, пожалуйста, просветите меня для правильного использования?
jquery
promise
jquery-deferred
screenm0nkey
источник
источник
Ответы:
Призванные обратные вызовы
done()
будут запущены, когда отложенное разрешение будет разрешено. Призванные обратные вызовыfail()
будут запущены, когда отложенное отклонено.До jQuery 1.8
then()
был просто синтаксический сахар:Начиная с версии 1.8
then()
это псевдоним дляpipe()
и возвращает новое обещание, смотрите здесь для получения дополнительной информацииpipe()
.success()
иerror()
доступны только дляjqXHR
объекта, возвращенного вызовомajax()
. Это простые псевдонимы дляdone()
иfail()
соответственно:Кроме того,
done()
не ограничивается одним обратным вызовом и будет отфильтровывать не-функции (хотя в версии 1.8 есть ошибка со строками, которая должна быть исправлена в 1.8.1):То же самое и для
fail()
.источник
then
возвращение нового обещания было ключевым моментом, которого мне не хватало. Я не мог понять, почему цепочка вроде$.get(....).done(function(data1) { return $.get(...) }).done(function(data2) { ... })
не работает сdata2
неопределенным; когда я переключилсяdone
наthen
это, это сработало, потому что я действительно хотел объединить обещания вместе, а не добавлять больше обработчиков к первоначальному обещанию.done
илиthen
? Почему?.then()
).Также есть разница в том, что возвращаемые результаты обрабатываются (это называется цепочкой,
done
не цепочкой, аthen
производит цепочки вызовов)Следующие результаты будут зарегистрированы:
Пока
получит следующее:
---------- Обновить:
Btw. Я забыл упомянуть, что если вы возвращаете Promise вместо атомарного значения типа, внешнее обещание будет ждать, пока внутреннее обещание не разрешится:
таким образом, становится очень простым составлять параллельные или последовательные асинхронные операции, такие как:
Приведенный выше код выдает два http-запроса параллельно, что ускоряет выполнение запросов, тогда как ниже этих http-запросов выполняется последовательно, что снижает нагрузку на сервер
источник
done
ничего не делает с результатом, гдеthen
изменяется результат. Огромный момент пропущен другими ИМО.then
изменилось в 1.8done
иthen
звонками.done
пример. Изменениеthen
кpipe
в пре-1.8 , чтобы получить 1.8+then
поведение..done()
имеет только один обратный вызов, и это обратный вызов успеха.then()
имеет как успешные, так и неудачные обратные вызовы.fail()
имеет только один неудачный обратный вызовтак что это зависит от вас, что вы должны сделать ... вас волнует, если это удастся или не получится?
источник
then()
сильно отличаются отdone()
. Какthen()
часто называют только при успешном обратном вызове, ваша точка зрения - это скорее деталь, а не главное, что нужно запомнить / знать. (Не могу сказать, как это было до jQuery 3.0.)deferred.done ()
добавляет обработчики, которые будут вызываться только после разрешения Deferred . Вы можете добавить несколько обратных вызовов для вызова.
Вы также можете написать выше, как это,
deferred.then ()
добавляет обработчики, которые будут вызываться, когда Deferred разрешен, отклонен или все еще выполняется .
источник
then
себя вести, еслиfail
обратный вызов не предоставляется, а именно - неfail
На самом деле есть довольно критическое различие, поскольку jQuery Deferreds предназначены для реализации Promises (а jQuery3.0 фактически пытается привести их в спецификацию).
Ключевое различие между готовым / затем заключается в том, что
.done()
ВСЕГДА возвращает те же значения Promise / wrapped, с которых он начинался, независимо от того, что вы делаете или что возвращаете..then()
всегда возвращает НОВОЕ Обещание, и вы отвечаете за контроль того, что это Обещание основано на том, какую функцию вы передали ему.Переведенный из jQuery в собственные обещания ES2015,
.done()
это своего рода реализация структуры "tap" вокруг функции в цепочке Promise, в которой он, если цепочка находится в состоянии "resol", передает значение функции .. но результат этой функции НЕ повлияет на саму цепочку.Те, кто будет регистрировать 5, а не 6.
Обратите внимание, что я использовал done и doneWrap для ведения журнала, а не .then. Это потому, что функции console.log на самом деле ничего не возвращают. И что произойдет, если вы передадите .then функцию, которая ничего не возвращает?
Это войдет:
Что случилось? Когда я использовал .then и передал ему функцию, которая ничего не возвращала, это неявный результат был «undefined» ... который, конечно, возвратил Promise [undefined] для следующего метода then, который записал в журнал undefined. Таким образом, первоначальная ценность, с которой мы начали, была в основном потеряна.
.then()
по сути, это форма композиции функции: результат каждого шага используется в качестве аргумента для функции на следующем шаге. Вот почему .done лучше всего рассматривать как «нажатие» -> это на самом деле не часть композиции, а просто что-то, что пробуждает взгляд на значение на определенном шаге и запускает функцию с этим значением, но на самом деле не меняет композиция никак.Это довольно фундаментальное различие, и, вероятно, есть веская причина, по которой нативные Promises не имеют реализованного метода .done. Нам не нужно разбираться, почему нет метода .fail, потому что он еще более сложен (а именно .fail / .catch НЕ являются зеркалами функций .done / .then -> в .catch, которые возвращают голые значения, не «остаться» отвергается, как те, которые были переданы. затем они решают!)
источник
then()
всегда означает, что он будет вызван в любом случае. Но передача параметров различна в разных версиях jQuery.До jQuery 1.8
then()
равняетсяdone().fail()
. И все функции обратного вызова имеют одинаковые параметры.Но, начиная с jQuery 1.8,
then()
возвращается новое обещание, и, если оно вернуло значение, оно будет передано в следующую функцию обратного вызова.Давайте посмотрим на следующий пример:
До jQuery 1.8 ответ должен быть
Все
result
занимает 3. Иthen()
функция всегда передает один и тот же отложенный объект следующей функции.Но начиная с jQuery 1.8, результат должен быть:
Потому что первая
then()
функция возвращает новое обещание, а значение 7 (и это единственный параметр, который будет передан) передается следующемуdone()
, поэтому втораяdone()
записьresult = 7
. Втораяthen()
принимает значение 7 в качестве значенияa
и принимает значение вundefined
качестве значенияb
, поэтому втораяthen()
возвращает новое обещание с параметром NaN, а последняяdone()
печатает NaN в качестве результата.источник
jQuery.Deferred()
, заключающийся в том, что a может принимать несколько значений, которые оно правильно передает первому.then()
. - Немного странно, хотя ... так как любое следующее.then()
не может этого сделать. (Выбранный интерфейс черезreturn
может возвращать только одно значение.) Нативный язык JavascriptPromise
этого не делает. (Что является более последовательным, если честно.)В ответе есть очень простое умственное отображение, которое было немного трудно найти в других ответах:
done
реализуетtap
как в обещаниях Bluebirdthen
реализуетthen
как в ES6 Promisesисточник
Использовать только
.then()
Это недостатки
.done()
resolve()
вызов блока (все.done()
обработчики будут выполняться синхронно)resolve()
может получить исключение из зарегистрированных.done()
обработчиков (!).done()
половину убивает отложенного:.done()
обработчики будут молча пропущеныЯ временно подумал, что это
.then(oneArgOnly)
всегда требует,.catch()
чтобы ни одно исключение не игнорировалось, но это уже не так:unhandledrejection
события регистрируют необработанные.then()
исключения на консоли (по умолчанию). Очень разумно! Нет причин использовать.done()
вообще.доказательство
Следующий фрагмент кода показывает, что:
.done()
обработчики будут называться синхронными в точкеresolve()
.done()
влиянииresolve()
resolve()
.done()
разрешения.then()
не имеет ни одной из этих проблемunhandledrejection
имеет, кажется)Кстати, исключения из
.done()
не могут быть правильно пойманы: из-за синхронного шаблона.done()
ошибка генерируется либо в точке.resolve()
(может быть библиотечный код!), Либо при.done()
вызове, который присоединяет виновника, если отложенное уже разрешено.источник
done
не будет выполнено, если предыдущий сделал исключение. Но почему это было бы тихо проигнорировано, я имею в виду, что произошло исключение, так почему вы говорите, что он молчит? 2) Я презираюDeferred
объект, потому что его API очень и очень плохо сделан. Это слишком сложно и запутанно. Ваш код здесь также не помогает доказать вашу точку зрения, и он имеет слишком много ненужной сложности для того, что вы пытаетесь доказать. 3) Почемуdone
в индексах 2, 4 и 6 выполняются до 2-гоthen
?.then()
будет вызвано, исключение (в этих обработчиках) поднято или нет. Но сложение / оставшийся.done()
перерыв.В jQuery 3.0 есть еще одно существенное отличие, которое может легко привести к неожиданному поведению и не упоминалось в предыдущих ответах:
Рассмотрим следующий код:
это выведет:
Теперь замените
done()
наthen()
тот же фрагмент:вывод сейчас:
Таким образом, для немедленно разрешенных отсрочек переданная функция
done()
всегда будет вызываться синхронно, тогда как любой переданный аргументthen()
вызывается асинхронно.Это отличается от предыдущих версий jQuery, где оба обратных вызова вызываются синхронно, как упомянуто в руководстве по обновлению :
источник
.done()
завершает цепочку обещаний, удостоверяясь, что больше ничего не может присоединить дальнейшие шаги. Это означает, что реализация обещания jQuery может выдать любое необработанное исключение, поскольку никто не может обработать его, используя.fail()
.В практическом плане, если вы не планируете добавлять дополнительные шаги к обещанию, вы должны использовать
.done()
. Для более подробной информации посмотрите, почему обещания должны быть выполненыисточник
.done()
нет завершающей роли. В документации сказано: «Так как deferred.done () возвращает отложенный объект, другие методы отложенного объекта могут быть связаны с этим, включая дополнительные методы .done ()»..fail()
не упоминается, но, да, это тоже может быть приковано.