Предположим, что у меня есть две асинхронные функции 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();
// ----
}
}
Как мне изменить код?
Вы возглавили правильный путь, но вы должны держать сцепление на 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
обрабатывать отклонения, или вы бы возвращали последнее обещание на другой код, который бы обрабатывал их.)
Вы можете цеплять вызовы с помощью 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); })
return
свои обещания.
Вы можете сделать это с помощью рекурсивной функции
function seqAB(count) {
if(!count) Promise.resolve();
var p1 = A();
p1.then(() => {
var p2 = B();
p2.then(() => {
seqAB(count - 1);
})
})
}
seqAB(200);
return
свои обещания, хотя