Мне нужно вызвать три функции один за другим. Для этого я использую jquery, отложенный "затем", чтобы связать вызовы.
Вот код:
function fillQuantity(x){
console.log('Q');
var deferred = jQuery.Deferred();
var intervalId = setInterval(function(){
clearInterval(intervalId);
console.log("Quantity: ", x);
deferred.resolve();
}, 2000);
return deferred.promise();
};
function fillPrice(x){
console.log('P');
var deferred = jQuery.Deferred();
var intervalId = setInterval(function(){
clearInterval(intervalId);
console.log("Price: ", x);
deferred.resolve();
}, 2000);
return deferred.promise();
};
function fillSection(x){
console.log('S');
var deferred = jQuery.Deferred();
var intervalId = setInterval(function(){
clearInterval(intervalId);
console.log("Section: ", x);
deferred.resolve();
}, 2000);
return deferred.promise();
};
var promise = jQuery.when().promise();
promise = promise.then(fillQuantity).then(fillPrice).then(fillSection);
promise.done(function(){
console.log('done');
});
В этом случае я должен иметь следующий результат:
Q
Количество: неопределенное
п
Цена: не определено
S
Раздел: неопределенный
сделанный
Но на самом деле я получил:
Q
п
S
сделанный
Количество: неопределенное
Цена: не определено
Раздел: неопределенный
Как я вижу, jQuery вызывает все три функции и игнорирует обещание. Что я делаю неправильно? Или что я не знаю о обещаниях jquery?
Благодарю.
Кажется, проблема была в версии jQuery.
1.6.1 - работает некорректно. 2.0.3 - работает как ожидалось
jQuery 1.6.1 был выпущен, когда обещания были новыми. И это было плохо.
Похоже, он был исправлен/изменен примерно на 1.8.3.
1.7.1 также не прошли тесты;
.then(fn)
вел себя как .done(fn)
, то есть .done(fn)
состояние входного обещания, а не обещание, возвращаемое функцией.
Я бы порекомендовал рассмотреть возможность использования обещания, совместимого с es6.
Огромный объем работы перешел в спецификацию обещаний es6, чтобы обеспечить правильность, что помогает предотвратить эти недостатки. К сожалению, jQuery в настоящее время может вызвать много горя. (как проблема, которую вы упомянули)
Кроме того, некоторые (и вскоре другие) вечнозеленые браузеры придут с такой реализацией. В настоящее время использование полифила, вероятно, подходит. Я бы предложил посмотреть https://github.com/jakearchibald/ES6-Promises
В любом случае, я реорганизовал ваш пример для работы с любой из совместимых с es6 реализаций, и теперь он работает так, как ожидалось.
function fillQuantity(x){
console.log('Q');
return new Promise(function(resolve){
var intervalId = setInterval(function(){
clearInterval(intervalId);
console.log("Quantity: ", x);
resolve();
}, 2000);
});
};
function fillPrice(x){
console.log('P');
return new Promise(function(resolve) {
var intervalId = setInterval(function(){
clearInterval(intervalId);
console.log("Price: ", x);
resolve();
}, 2000);
});
};
function fillSection(x){
console.log('S');
return new Promise(function(resolve){
var intervalId = setInterval(function(){
clearInterval(intervalId);
console.log("Section: ", x);
resolve();
}, 2000);
});
};
var promise = Promise.resolve();
promise.
then(fillQuantity).
then(fillPrice).
then(fillSection).
then(function(){
console.log('done');
});
вывод:
Quantity: undefined
P
Price: undefined
S
Section: undefined
done
$.when()
без аргументов вместо того, чтобы выдаватьfillQuantity().then(fillPrice).then(fillSection)
?$.when(fillQuantity, fillPrice, ...).then()
это не должно быть$.when(fillQuantity, fillPrice, ...).then()
?