Поскольку jQuery 1.8 .then ведет себя так же, как .pipe:
Уведомление об deferred.pipe()устаревании. Начиная с jQuery 1.8, этот метод устарел. deferred.then()Метод, который заменяет его, вместо него следует использовать.
и
Начиная с jQuery 1.8 , deferred.then()метод возвращает новое обещание, которое может фильтровать статус и значения отложенного с помощью функции, заменяя устаревший deferred.pipe()метод.
Приведенные ниже примеры могут быть полезны некоторым.
Они служат разным целям:
.then()должен использоваться всякий раз, когда вы хотите работать с результатом процесса, то есть, как говорится в документации, когда отложенный объект разрешен или отклонен. Это то же самое, что использовать .done()или .fail().
Вы бы как-то использовали .pipe()(предварительную) фильтрацию результата. Возвращаемое значение обратного вызова для .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, не раскрывая фактический поток / порядок вызовов.
В общем, отложенные объекты предоставляют интересный способ отделить ваш код :)