В jQuery Deferred
есть две функции, которые можно использовать для реализации асинхронной цепочки функций:
then()
deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred
doneCallbacks Функция или массив функций, вызываемый при разрешении Deferred.
failCallbacks Функция или массив функций, вызываемых при отклонении Deferred.
pipe()
deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise
doneFilter Необязательная функция, которая вызывается при разрешении Deferred.
failFilter Необязательная функция, которая вызывается при отклонении отложенного.
Я знаю, then()
что он существует немного дольше, pipe()
поэтому последний должен добавить некоторую дополнительную пользу, но какая именно разница ускользает от меня. Оба принимают практически одинаковые параметры обратного вызова, хотя они различаются по имени, и разница между возвратом a Deferred
и возвратом a Promise
кажется незначительной.
Я читал официальные документы снова и снова, но всегда нахожу их слишком "плотными", чтобы по-настоящему осмыслить мою голову, и поиск нашел много обсуждений той или иной функции, но я не нашел ничего, что действительно разъясняло бы разные плюсы и минусы каждого.
Итак, когда лучше использовать, then
а когда лучше использовать pipe
?
Дополнение
Отличный ответ Феликса действительно помог прояснить, чем отличаются эти две функции. Но мне интересно, бывают ли случаи, когда функциональность более then()
предпочтительна, чем функциональность pipe()
.
Очевидно, что pipe()
он более могущественен, then()
и кажется, что первый может делать все, что может сделать второй. Одна из причин для использования then()
может заключаться в том, что его имя отражает его роль в качестве завершения цепочки функций, обрабатывающих одни и те же данные.
Но существует ли вариант использования, требующий then()
возврата оригинала, Deferred
который не может быть выполнен pipe()
из-за возврата нового Promise
?
источник
Ответы:
Поскольку jQuery 1.8
.then
ведет себя так же, как.pipe
:и
Приведенные ниже примеры могут быть полезны некоторым.
Они служат разным целям:
.then()
должен использоваться всякий раз, когда вы хотите работать с результатом процесса, то есть, как говорится в документации, когда отложенный объект разрешен или отклонен. Это то же самое, что использовать.done()
или.fail()
.Вы бы как-то использовали
.pipe()
(предварительную) фильтрацию результата. Возвращаемое значение обратного вызова для.pipe()
будет передано в качестве аргумента кdone
иfail
обратным вызовам. Он также может вернуть другой отложенный объект, и следующие обратные вызовы будут зарегистрированы на этом отложенном.Это не относится к
.then()
(или.done()
,.fail()
), возвращаемые значения зарегистрированных обратных вызовов просто игнорируются.Так что дело не в том, что вы используете либо
.then()
или.pipe()
. Вы можете использовать его.pipe()
для тех же целей,.then()
но обратное неверно.Пример 1
Результатом некоторой операции является массив объектов:
и вы хотите вычислить минимальное и максимальное значения. Предположим, мы используем два
done
обратных вызова:В обоих случаях вам нужно перебрать список и извлечь значение из каждого объекта.
Разве не было бы лучше заранее каким-то образом извлечь значения, чтобы вам не приходилось делать это в обоих обратных вызовах по отдельности? Да! И это то, что мы можем использовать
.pipe()
для:Очевидно, что это выдуманный пример, и есть много разных (может быть, лучших) способов решить эту проблему, но я надеюсь, что он иллюстрирует суть.
Пример 2
Рассмотрим вызовы Ajax. Иногда вы хотите инициировать один вызов Ajax после завершения предыдущего. Один из способов - сделать второй вызов внутри
done
обратного вызова:Теперь предположим, что вы хотите отделить свой код и поместить эти два вызова Ajax внутри функции:
Вы хотели бы использовать отложенный объект, чтобы разрешить другой код, который вызывает
makeCalls
присоединение обратных вызовов для второго вызова Ajax, ноне будет иметь желаемого эффекта, поскольку второй вызов выполняется внутри
done
обратного вызова и недоступен извне.Решением было бы использовать
.pipe()
вместо этого:Используя
.pipe()
теперь, вы можете добавить обратные вызовы к «внутреннему» вызову Ajax, не раскрывая фактический поток / порядок вызовов.В общем, отложенные объекты предоставляют интересный способ отделить ваш код :)
источник
pipe
может делать фильтрацию, чегоthen
не может. Но при поиске в Google эти темы, кажется, они выбрали называть это,pipe
а неfilter
потому, что считали фильтрацию чем-то вроде дополнительного бонуса, который идет вместе с ней, тогда какpipe
более четко указывали ее истинную цель. Похоже, помимо фильтрации должны быть и другие отличия. (С другой стороны, я признаю, что не совсем понимаю функцию фильтрации даже с вашими примерами. Должноresult values;
бытьreturn values;
, кстати?).then()
получают те же данные,result
которые вы фильтруете каждый раз; тогда как в нижнем примере, перед передачей.pipe()
удаляет часть данныхresult
, посколькуresult
два последующих.then()
s получат?.pipe()
. Если обратный вызов возвращает отложенный объект, для этого объекта будут зарегистрированы последующие обратные вызовы выполненного или неудачного выполнения. Приведу еще один пример. изменить: относительно вашего второго комментария: да.pipe()
тогда какthen()
это больше похоже на листовой узел, в конце которого вы должны использовать свои данные, и он не течет дальше, и что, несмотря на тот факт, что онthen()
возвращает,Deferred
он фактически не используется / не полезен? Если это правильно, может помочь уточнить включение чего-то вроде/* do something with "min"/"max" */
в каждое предложение ".then ()".Нет случая, когда вы ДОЛЖНЫ использовать
then()
overpipe()
. Вы всегда можете игнорировать значение, котороеpipe()
будет передано. При использовании может быть небольшое снижение производительности,pipe
но это вряд ли имеет значение.Так что может показаться, что вы всегда можете использовать
pipe()
в обоих случаях. Однако , используяpipe()
, вы сообщаете другим людям, читающим ваш код (включая вас, через шесть месяцев), что возвращаемое значение имеет некоторую важность . Если вы отказываетесь от него, вы нарушаете эту семантическую конструкцию.Это похоже на функцию, которая возвращает значение, которое никогда не используется: сбивает с толку.
Так что используйте,
then()
когда нужно, аpipe()
когда нужно ...источник
$(function () { $.when(getPosition()) .pipe(lookupCountry) .then(displayResults); });
«Обратите внимание, что pipe отличается от потом, потому что pipe дает новое обещание ".На самом деле оказалось, что разница между
.then()
и.pipe()
была сочтена ненужной, и они были сделаны такими же, как и в jQuery версии 1.8.Из комментария
jaubourg
в тикете системы отслеживания ошибок jQuery № 11010 «MAKE DEFERRED.THEN == DEFERRED.PIPE LIKE PROMISE / A»:(мина emphassis)
источник