jQuery «.then ()» не является последовательным и работает не так, как ожидалось

0

Мне нужно вызвать три функции один за другим. Для этого я использую 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?

Благодарю.

  • 0
    Есть ли причина, по которой вы вызываете $.when() без аргументов вместо того, чтобы выдавать fillQuantity().then(fillPrice).then(fillSection) ?
  • 0
    $.when(fillQuantity, fillPrice, ...).then() это не должно быть $.when(fillQuantity, fillPrice, ...).then() ?
Показать ещё 6 комментариев
Теги:
promise
jquery-deferred

2 ответа

1
Лучший ответ

Кажется, проблема была в версии jQuery.

1.6.1 - работает некорректно. 2.0.3 - работает как ожидалось

jQuery 1.6.1 был выпущен, когда обещания были новыми. И это было плохо.

Похоже, он был исправлен/изменен примерно на 1.8.3.

1.7.1 также не прошли тесты;

  • 0
    Этот ответ правильный согласно описанной проблеме. Так что, если вы не понимаете, не голосуйте.
  • 1
    pro100саня, да могу подтвердить ваши выводы. ОК с JQuery 1.8.3. В более ранних версиях .then(fn) вел себя как .done(fn) , то есть .done(fn) состояние входного обещания, а не обещание, возвращаемое функцией.
Показать ещё 1 комментарий
2

Я бы порекомендовал рассмотреть возможность использования обещания, совместимого с 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
  • 0
    Если я вас правильно понял, мне нужно добавить еще одну библиотеку обещаний и использовать свои собственные обещания, а не обещания jquery?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню