Ответ 1
Так как jQuery 1.8 .then
ведет себя так же, как .pipe
:
Уведомление об изнашивании: Как и в jQuery 1.8, метод
deferred.pipe()
устарел. Вместо этого следует использовать методdeferred.then()
, который заменяет его.
и
С jQuery 1.8 метод
deferred.then()
возвращает новое обещание, которое может фильтровать состояние и значения отложенных через функцию, заменяя теперь устаревший методdeferred.pipe()
.
Нижеприведенные примеры могут быть полезны для некоторых.
Они служат для разных целей:
-
.then()
должен использоваться всякий раз, когда вы хотите работать с результатом процесса, то есть, как говорится в документации, когда отложенный объект разрешен или отклонен. Это то же самое, что использовать.done()
или.fail()
. -
Вы использовали бы
.pipe()
для (pre) для фильтрации результата. Возвращаемое значение обратного вызова на.pipe()
будет передано в качестве аргумента для обратных вызововdone
иfail
. Он также может вернуть другой объект с отсрочкой, и на этом отсрочке будут зарегистрированы следующие обратные вызовы.Это не относится к
.then()
(или.done()
,.fail()
), возвращаемые значения зарегистрированных обратных вызовов просто игнорируются.
Таким образом, вы не используете либо .then()
, либо .pipe()
. Вы можете использовать .pipe()
для тех же целей, что и .then()
, но обратное не выполняется.
Пример 1
Результатом некоторой операции является массив объектов:
[{value: 2}, {value: 4}, {value: 6}]
и вы хотите вычислить минимальные и максимальные значения. Предположим, мы используем два обратных вызова done
:
deferred.then(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
var min = Math.min.apply(Math, values);
/* do something with "min" */
}).then(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
var max = Math.max.apply(Math, values);
/* do something with "max" */
});
В обоих случаях вам нужно перебирать список и извлекать значение из каждого объекта.
Не было бы лучше каким-то образом извлечь значения заранее, чтобы вам не приходилось делать это в обоих обратных вызовах индивидуально? Да! И это то, что мы можем использовать .pipe()
для:
deferred.pipe(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
return values; // [2, 4, 6]
}).then(function(result) {
// result = [2, 4, 6]
var min = Math.min.apply(Math, result);
/* do something with "min" */
}).then(function(result) {
// result = [2, 4, 6]
var max = Math.max.apply(Math, result);
/* do something with "max" */
});
Очевидно, что это составленный пример, и есть много разных (возможно, лучших) способов решения этой проблемы, но я надеюсь, что это иллюстрирует суть.
Пример 2
Рассмотрим Ajax-вызовы. Иногда вы хотите инициировать один вызов Ajax после завершения предыдущего. Один из способов - сделать второй вызов внутри обратного вызова done
:
$.ajax(...).done(function() {
// executed after first Ajax
$.ajax(...).done(function() {
// executed after second call
});
});
Теперь давайте предположим, что вы хотите развязать свой код и поместить эти два вызова Ajax внутри функции:
function makeCalls() {
// here we return the return value of `$.ajax().done()`, which
// is the same deferred object as returned by `$.ajax()` alone
return $.ajax(...).done(function() {
// executed after first call
$.ajax(...).done(function() {
// executed after second call
});
});
}
Вы хотите использовать отложенный объект, чтобы разрешить другой код, который вызывает makeCalls
для присоединения обратных вызовов для второго вызова Ajax, но
makeCalls().done(function() {
// this is executed after the first Ajax call
});
не будет иметь желаемого эффекта, поскольку второй вызов выполняется внутри обратного вызова done
и недоступен извне.
Вместо этого было бы использовать .pipe()
:
function makeCalls() {
// here we return the return value of `$.ajax().pipe()`, which is
// a new deferred/promise object and connected to the one returned
// by the callback passed to `pipe`
return $.ajax(...).pipe(function() {
// executed after first call
return $.ajax(...).done(function() {
// executed after second call
});
});
}
makeCalls().done(function() {
// this is executed after the second Ajax call
});
Используя .pipe()
, вы можете теперь добавить обратные вызовы к "внутреннему" вызову Ajax, не подвергая действительный поток/порядок вызовов.
В общем, отложенные объекты предоставляют интересный способ отделить ваш код:)