将 then 附加到调用堆栈下多级承诺的最佳解决方案是什么?

What is the best solution to attaching a then onto a promise multi-level down the call stack?

考虑这样一个场景:

function func_topmost(){
    ...
    func_layer1();
    pseudo_code for some actions here; // an action that needs to run AFTER the promise in func_layer2 fulfilled.
}

function func_layer1(){
    ...
    func_layer2();
}

function func_layer2(){
    var the_vital_promise = $.post('very_slow_backend_response', data);
    return the_vital_promise;
}

以上只是一个例子。实际上调用栈可能更深,在未来的开发中总是有可能在调用栈中引入另一层功能。

我的问题是,确保最顶层中依赖于正确附加的承诺的履行的最顶层中的操作的最佳实践是什么?

现在我能想到的是将调用链中的所有函数async function一直放到底部。我不确定这是否是正确的解决方案,并且它使后期维护非常僵化。

如果我理解你的意图是正确的,那么只需将承诺返回到最顶层的函数并在该承诺上调用 then 即可:

function func_topmost(){
    ...
    func_layer1().then(function(param){
        // Your action here after resolving the promise
    }).catch(function(){
        // Your code on rejection of the promise
    });

}

function func_layer1(){
    ...
    return func_layer2();
}

function func_layer2(){
    var the_vital_promise = $.post('very_slow_backend_response', data);
    return the_vital_promise;
}

第二种方法,如果你想链接 func_layer1(提前知道会更好)是提供回调的动作:

function func_topmost(){
    func_layer1( 
        function(){
            // Code on completion
        },
        function(){
            // Code on rejection
        });
 }

function func_layer1( onResolve, onReject ){
    func_layer2().then( onResolve, onReject );
}

...

所以你有多个正常的函数互相调用,突然间堆栈顶部的那个函数恰好处理一些异步任务,你正在寻找一种方法来用最少的代码更改来解决这个问题。我知道有 3 种方法可以处理这个问题,其中 2 种已经被提到,但我认为它们有一些缺点。

1.返回承诺

  • 会破坏代码结构
  • 需要更改所有功能

2。 Async/await

async function func_topmost(){
    const data = await func_layer1();
    pseudo_code for some actions here; // an action that needs to run AFTER the promise in func_layer2 fulfilled.
}

function func_layer1(){
    const promise = func_layer2();
    return promise;
}

function func_layer2(){
    var the_vital_promise = $.post('very_slow_backend_response', data);
    return the_vital_promise;
}
  • 代码更改比返回承诺少,但编译包中的代码更多
  • 需要更改所有功能

3。发送一个事件

如果您有很多函数堆叠在一起,这对我来说似乎是处理问题的最佳方式。如果您在 Node 上,则可以使用事件库,如果环境是浏览器,则可以使用自定义 DOM 事件。这样你只需要改变第一个和最后一个函数(如果中间的函数不依赖于承诺完成)并且代码结构保持不变。

function func_layer2(){
    var the_vital_promise = $.post('very_slow_backend_response', data)
    .then(res => {
         events.emit('customEvent');
     });
    return the_vital_promise;
}

function func_topmost(){
    ...
    events.on('customEvent', () => {
         pseudo_code for some actions here; // an action that needs to run AFTER the promise in func_layer2 fulfilled.
    });
    func_layer1();
}