Как выполнить несколько асинхронных функций последовательно несколько раз?

1

Предположим, что у меня есть две асинхронные функции A и B, которые независимы друг от друга.

То, что я пытаюсь сделать, - это выполнить эти функции последовательно несколько раз, как показано ниже

A -> B -> A -> B -> A -> ... 

B ждет, пока A не закончится, и наоборот.

Следующее - это то, что я сделал до сих пор, и я знаю, что он не будет работать так, как я хочу.

function A() {
  var promise = new Promise...
  ...
  return promise;
}

function B() {
  var promise = new Promise...
  ...
  return promise;
}

for(var i=0; i<200; i++) {
  var p1 = A();
  p1.then(() => {
   var p2 = B();
   // ----
  }
}

Как мне изменить код?

Теги:
asynchronous

3 ответа

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

Вы возглавили правильный путь, но вы должны держать сцепление на then с. Как правило, вы начинаете с заранее решено обещанием Promise.resolve() затем добавить к цепи, используя then, сохраняя каждое новое обещание:

let p = Promise.resolve();
for (var i=0; i<200; i++) {
  p = p.then(A).then(B);
}
p.then(() => {
  console.log("All done");
});

Живой пример (с 20 вместо 200):

let counterA = 0;
let counterB = 0;

function A() {
  var promise = new Promise(resolve => {
    setTimeout(() => {
      ++counterA;
      console.log("A done (" + counterA + ")");
      resolve();
    }, 100);
  });
  return promise;
}

function B() {
  var promise = new Promise(resolve => {
    setTimeout(() => {
      ++counterB;
      console.log("B done (" + counterB + ")");
      resolve();
    }, 100);
  });
  return promise;
}

let p = Promise.resolve();
for (var i=0; i<20; i++) {
  p = p.then(A).then(B);
}
p.then(() => {
  console.log("All done");
});
.as-console-wrapper {
  max-height: 100% !important;
}

(В реальном коде вы, .catch, тоже должны были бы .catch обрабатывать отклонения, или вы бы возвращали последнее обещание на другой код, который бы обрабатывал их.)

  • 0
    Работал! Спасибо.
1

Вы можете цеплять вызовы с помощью chained.then() чтобы убедиться, что они вызываются после того, как предыдущие выполнены.

let cA = cB = 0;
function A() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("A " + ++cA);
            console.log("A done");
        }, 200);
    });
}

function B() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("B " + ++cB);
            console.log("B done");
        }, 300);
    });
}

function callConsecutive(times) {
    if (times == 0) return Promise.resolve([]);
    times--;
    const a = A(),
          b = a.then(B),
          c = b.then(() => { return callConsecutive(times) });
    return Promise.all([a, b, c]).then(([r1,r2,r3]) => Promise.resolve([r1,r2,...r3]));
}
callConsecutive(5).then(results => { console.log(results); })
  • 1
    Не забывайте return свои обещания.
  • 0
    @ Берги, а я нет?
Показать ещё 3 комментария
0

Вы можете сделать это с помощью рекурсивной функции

function seqAB(count) {
  if(!count) Promise.resolve();
  var p1 = A();
  p1.then(() => {
    var p2 = B();
    p2.then(() => {
      seqAB(count - 1);
    })
  })
}


seqAB(200);
  • 0
    Uncaught SyntaxError: отсутствует) после списка аргументов L7
  • 1
    Не забудьте return свои обещания, хотя
Показать ещё 2 комментария

Ещё вопросы

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