使用承诺递归意味着注册的回调会被多次调用



所以我的想法是对的,当用 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);
});

最新更新