所以我的想法是对的,当用 promise 递归时,我们最终会调用所有链式回调,无论我们递归多少次,例如
function p() {
return new Promise(function (r) {
process.nextTick(r);
})
}
function recurse(count) {
return p().then(function () {
if (count < 10) {
console.log('count => ', count);
return recurse(++count);
}
}).then(function(){
console.log('a');
return 5;
});
}
recurse(1).then(function () {
console.log('done');
});
如果您运行上述操作,我们将得到:
count => 1
count => 2
count => 3
count => 4
count => 5
count => 6
count => 7
count => 8
count => 9
a
a
a
a
a
a
a
a
a
a
done
有没有办法只向 console.log('a') 注册此回调一次,而不是注册 10 次?
我认为我不希望/需要调用此函数 10 次,并希望找到一种方法只调用一次。
实际上,我对Observables的类似解决方案同样感兴趣,特别是RxJS5 Observables。
我想唯一的解决方案是将代码的其余部分嵌套在第一个 promise 回调中,如下所示:
function p() {
return new Promise(function (r) {
process.nextTick(r);
})
}
function recurse(count) {
return p().then(function () {
if (count < 10) {
return recurse(++count);
} else {
// all your remaining code would have to go here
console.log('a');
return 5; // or return someOtherPromise() or anything
}
});
}
recurse(1).then(function () {
console.log('done');
});
如果递归是同步的,你可以简单地在.then
函数内递归
new Promise(res => {
res(); // dummy initial promise
}).then(() => {
function recurse(x) { // recursion inside then
console.log('x', x);
if (x < 10) return recurse(++x);
return x;
}
return recurse(1); // begin recursion
}).then(y => { // this only fires once recursion above is resolved
console.log('y', y);
return 5;
}).then(z => console.log('z', z));
// x 1
// ... (synchronous)
// x 10
// y 10 (value passed from resolving inner promise)
// z 5 (value returned from previous then)
或者,如果我们的递归函数是异步的,我们也可以让它返回一个承诺,所以你最终会得到一个递归,看起来像这样。
function doWork() {
function addOne(x) {
return new Promise((res, rej) => {
// async bit here
res(x + 1);
});
}
function recurse(x) {
if (x < 10) return addOne(x).then(recurse);
return x;
}
return recurse(1);
}
在承诺链中,看起来像这样
new Promise(res => {
res(); // dummy initial promise
}).then(() => {
return doWork();
}).then(y => {
console.log(y);
});