Подтвердить что ты не робот

JQuery Отложенные и обещающие для последовательного выполнения синхронных и асинхронных функций

Если я хочу, чтобы синхронные и асинхронные функции выполнялись в определенном порядке, я мог бы использовать jQuery-обещание, но он, похоже, не работает так, как я ожидаю, что он будет работать.

Функции a, b и c должны выполняться в том порядке, когда в deferred.resolve() вызывается, я ожидаю, что функция b будет выполнена, но все функции выполняются немедленно независимо от того, вызывается ли это решение.

Вот код:

function a(){
  var deferred = $.Deferred();
  setTimeout(function(){
    console.log("status in a:",deferred.state());
    //this should trigger calling a or not?
    deferred.resolve("from a");
  },200);
  console.log("a");
  return deferred.promise();
};
function b(){
  var deferred = $.Deferred();
  setTimeout(function(){
    console.log("status in b:",deferred.state());
    deferred.resolve("from b");
  },200);
  console.log("b");
  return deferred.promise();
}
//synchronous function
function c(){
  var deferred = $.Deferred();
  console.log("c");
  console.log("status in c:",deferred.state());
  deferred.resolve("from c");
  return deferred.promise();
}
function test(){
  fn=[a,b,c],i=-1,
  len = fn.length,d,
  d = jQuery.Deferred(),
  p=d.promise();
  while(++i<len){
    p=p.then(fn[i]);
  }
  p.then(function(){
    console.log("done");
  },
  function(){
    console.log("Failed");
  });
  d.resolve();
  //instead of the loop doing the following has the same output
  //p.then(a).then(b).then(c);
  //d.resolve();
}
test();

Выход:

a
b
status in c: pending
c
done
status in a: pending
status in b: pending

Ожидаемый результат:

a
status in a: pending
b
status in b: pending
c
status in c: pending
done

Пробовали некоторые комбинации следующих модификаций:

  d = jQuery.Deferred();
  setTimeout(function(){d.resolve();},100);
  var p=d.promise();
  while(++i<len){
    p.then(fn[i]);
  }

Но все с такими же неожиданными результатами, b вызывается до того, как отложен запрос на a, разрешен, c вызывается до того, как отложен запрос b.

4b9b3361

Ответ 1

Для jQuery до 1.8 это проблема, но для новых версий jQuery это уже не проблема:

function test(){
  var d = jQuery.Deferred(), 
  p=d.promise();
  //You can chain jQuery promises using .then
  p.then(a).then(b).then(c);
  d.resolve();
}
test();

DEMO

Ниже приведена демонстрация jQuery 1.7.2

DEMO

Ответ 2

jQuery < 1.8 - это отличная цепочка WRT, вы просто используете .pipe вместо .then. 1.8 просто изменил .then на .pipe.

Ответ 3

Sidenote: когда вы используете его без массива, вам не нужно начинать с обещания. $.when({}).then(a).then(b) сделает трюк просто отлично. Вам нужно только убедиться, что вы не ставите a внутри when.