Правильный способ связать два обещания, когда второе обещание зависит от первого?

Как сделать цепочку из двух асинхронных вызовов JQuery с помощью JS Promises, избегая при этом пирамиды гибели? Я знаю, что могу преобразовать обещание "JQuery" в реальное обещание следующим образом:

Promise.resolve($.getJSON(url, params));

Если я просто хочу дождаться одного обещания, я могу сделать это:

Promise.resolve($.getJSON(url1, params1))
.then(function(result){
  // do stuff
});

Если я хочу дождаться выполнения двух разных вызовов ajax, я могу сделать это:

Promise.all(
[
  Promise.resolve($.getJSON(url1, params1)),
  Promise.resolve($.getJSON(url2, params2))
]).then(function(results_array){
  // do stuff
});

Однако, если я хочу, чтобы один вызов следовал за другим, это не сработает:

Promise.resolve($.getJSON(url1, params1))
.then(function(result){
  //do stuff
  return Promise.resolve($.getJSON(url2, params2));
}).then(function(result){
  //result is a promise, not the results from the second call to getJSON()...
  //and it doesn't even wait for the second call to finish.
  //result.then() is just going to bring me further into the pyramid of doom :(
});

Каким-то образом я хочу вызвать .then() для обещания, созданного в функции «делать вещи». Какой идиоматический способ сделать это?


person user3928094    schedule 08.07.2015    source источник
comment
У вас есть две дополнительные закрывающие скобки вокруг result   -  person hazzik    schedule 09.07.2015


Ответы (1)


return Promise.resolve($.getJSON(url2, params2));

Что вы сделали, так это создали уже разрешенное обещание (через Promise.resolve), разрешенное значение которого является результатом $.get(), которое также является обещанием. Вот почему «он даже не ждет завершения второго вызова» и «результат обещан».

Кроме того, вам не нужно оборачивать вызовы jQuery AJAX, поскольку они возвращают промисы. Промисы jQuery действуют почти (но не полностью) так же, как нативные промисы.

Сделайте это вместо этого:

$.getJSON(url1, params1).then(function(result)){
  return $.getJSON(url2, params2);
}).then(function(result)){
  //result 2
});

Кроме того, вы используете jQuery. jQuery AJAX с промисами можно сделать так:

$.getJSON(url1, params1).then(function(result){
  // do stuff
});

Прослушивание нескольких промисов можно сделать в jQuery следующим образом:

$.when($.getJSON(...), $.getJSON(...)).then(function(res1, res2){
  // do stuff
});
person Joseph    schedule 08.07.2015
comment
разве результат2 не является обещанием, а не ответом на второй вызов getJSON? - person user3928094; 08.07.2015
comment
@ user3928094 нет. Я возвращаю обещание, которое разрешается с результатом AJAX. Что вы сделали, так это вернули обещание, которое разрешается обещанием. - person Joseph; 09.07.2015
comment
тогда почему Promise.resolve($.ajax(url, params)).then() работает? В том смысле, что это также обещание, которое разрешается обещанием... Есть ли способ сделать то, что я делаю, со стандартными обещаниями EMCA, полностью избегая обещаний jquery? - person user3928094; 09.07.2015
comment
@user3928094 user3928094 Если у вас возникнут дополнительные вопросы, задайте другой вопрос. meta.stackoverflow.com/q/266767/575527. Я считаю, почему возврат обещания, разрешенного с помощью обещания, не работает при возврате из then? и Как полностью избежать обещаний jQuery? ваши последующие действия. - person Joseph; 09.07.2015