问题 避免使用promises进行嵌套回调


我还是新手使用Promise API,我正在努力避免深度嵌套的Promise链,据我所知,这是使用Promise的好处之一。使用以下伪代码作为示例,当后续的依赖于先前的上下文时,如何避免嵌套Promise?

function loadDependency1() {
    // return a promsise to load the first dependency
}

function loadDependency2(dependency1) {
    // return a promise to load the second dependency, which relies on the first dependency
}

function loadDependency3(dependency2) {
    // return a promise to load the third dependency, which relies on the second dependency
}

function doWork(dependency1, dependency2, dependency3) {
    // finally have all the things necessary to do work
}

// load all the dependencies and eventually doWork
loadDependency1().then(function(dependency1) {
    return loadDependency2(dependency1).then(function(dependency2) {
        return loadDependency3(dependency2).then(function(dependency3) {
            doWork(dependency1, dependency2, dependency3);
        });
    });
});

2696
2018-01-20 19:25


起源



答案:


当你从中回复承诺时 then,它会解决 当那个承诺解决了

所以,如果下一个只需要前一个:

loadDependency1().then(function(dependency1) {
    return loadDependency2(dependency1);
}).then(function(dependency2) {
     return loadDependency3(dependency2);
}).then(function(dependency3) {
    doWork(dependency3);
});

如果您需要第三个依赖项,则有效。

如果依赖关系不依赖于彼此:

Promise.all([loadDependency1(),loadDependency2(),loadDependency3])
.spread(function(dep1,dep2,dep3){
    doWork(dep1,dep2,dep3);
});

如果你想在整个承诺链中保持“状态”并使用现代的承诺库,例如 知更鸟 你可以做:

loadDependency1().bind({}).then(function(dependency1) {
    this.dep1 = dependency1;
    return loadDependency2(dependency1);
}).then(function(dependency2) {
     this.dep2 = dependency2;
     return loadDependency3(dependency2);
}).then(function(dependency3) {
    doWork(this.dep1, this.dep2, dependency3);
});

如果你不是(你真的应该:))你可以 .all 你绕过它:

loadDependency1().then(function(dependency1) {
    return [loadDependency2(dependency1),dependency1];
}).spread(function(dependency2,dep1) {
     return [loadDependency3(dependency2),dependency2,dep1];
}).spread(function(dependency3,dependency2,dependency1) {
    doWork(dependency1, dependency2, dependency3);
});

13
2018-01-20 19:31



请在第一个示例中删除那些不必要的lambdas: loadDependency1().then(loadDependency2).then(loadDependency3).then(doWork); - Bergi
@Bergi那些lambdas用于说明“线性”控制流的指导性目的。我完全了解第一顺序功能:)虽然好评。 - Benjamin Gruenbaum


答案:


当你从中回复承诺时 then,它会解决 当那个承诺解决了

所以,如果下一个只需要前一个:

loadDependency1().then(function(dependency1) {
    return loadDependency2(dependency1);
}).then(function(dependency2) {
     return loadDependency3(dependency2);
}).then(function(dependency3) {
    doWork(dependency3);
});

如果您需要第三个依赖项,则有效。

如果依赖关系不依赖于彼此:

Promise.all([loadDependency1(),loadDependency2(),loadDependency3])
.spread(function(dep1,dep2,dep3){
    doWork(dep1,dep2,dep3);
});

如果你想在整个承诺链中保持“状态”并使用现代的承诺库,例如 知更鸟 你可以做:

loadDependency1().bind({}).then(function(dependency1) {
    this.dep1 = dependency1;
    return loadDependency2(dependency1);
}).then(function(dependency2) {
     this.dep2 = dependency2;
     return loadDependency3(dependency2);
}).then(function(dependency3) {
    doWork(this.dep1, this.dep2, dependency3);
});

如果你不是(你真的应该:))你可以 .all 你绕过它:

loadDependency1().then(function(dependency1) {
    return [loadDependency2(dependency1),dependency1];
}).spread(function(dependency2,dep1) {
     return [loadDependency3(dependency2),dependency2,dep1];
}).spread(function(dependency3,dependency2,dependency1) {
    doWork(dependency1, dependency2, dependency3);
});

13
2018-01-20 19:31



请在第一个示例中删除那些不必要的lambdas: loadDependency1().then(loadDependency2).then(loadDependency3).then(doWork); - Bergi
@Bergi那些lambdas用于说明“线性”控制流的指导性目的。我完全了解第一顺序功能:)虽然好评。 - Benjamin Gruenbaum