Javascript 蓝鸟:如何绑定承诺,以便我可以在.catch中自定义行为,然后允许错误继续级联?

Javascript 蓝鸟:如何绑定承诺,以便我可以在.catch中自定义行为,然后允许错误继续级联?,javascript,promise,bluebird,Javascript,Promise,Bluebird,注意-请参阅下面的更新 我想要一个在第一个任务和其他辅助任务之间的执行之间具有依赖关系的流,但是其他辅助任务都可以并发运行。 我想写一个干净的流,这将使它容易处理错误,我已经尝试了几种变化,但不能得到正确的 以下是我将要使用的内容,无论我如何编写它: var primaryAsyncTask = {...}; //single 'task' which has an execution function var secondaryAsyncTasks = [{...}]; //array of

注意-请参阅下面的更新

我想要一个在第一个任务和其他辅助任务之间的执行之间具有依赖关系的流,但是其他辅助任务都可以并发运行。 我想写一个干净的流,这将使它容易处理错误,我已经尝试了几种变化,但不能得到正确的

以下是我将要使用的内容,无论我如何编写它:

var primaryAsyncTask  = {...}; //single 'task' which has an execution function
var secondaryAsyncTasks = [{...}]; //array of tasks with same format as above
function promisifyTask(task){ .... }; //returns a promise which executes the task and appends the resolve/reject functions as the last arguments to the task execution function
下面是我目前尝试的两个选项:

  • 在promisifyTask中,我包装拒绝处理程序并将其绑定到任务,这样我就可以自定义失败信息,然后在最终捕获时检查它。换句话说,流程如下所示:
  • 这里的优点是,如果主任务失败,它不会执行辅助任务,并在catch中到达onFail。。。但是如果成功,它将执行它们,并且只有其中一个失败时才会到达onFail(这也是所需的行为)

  • 或者,在内部看起来更好的方法是绑定承诺并捕获它,而不是包装拒绝处理程序,然后我可以在一个“taskFailCatcher”函数中处理所有事情,因此看起来如下所示:

    function onTaskFail(reason){
        //do something to save info from reason onto this = task, since it was bound before the catch
    }
    
    function promisifyTask(task){
        return new Promise(function(resolve, reject) {
            task.execute.apply(null, task.args.concat([resolve, reject]));
        });
    }
    function promisifyTaskAndCatch(task){
        return promisifyTask(task).bind(task).catch(onTaskFail)
    }
    //and then when executing:
    promisifyTask(primaryAsyncTask)
                .then(function (){
                       return Promise.settle(secondaryAsyncTasks.map(function (task) {
                            return promisifyTaskAndCatch(task);
                       }));
                 })
                .then(function onSuccess(){...})
                .catch(function onFail(){...})
    
  • 我喜欢.bind.catch,但这里的问题有两个:

  • 流程不一致。我不想在主任务失败时执行辅助任务,因此我对主任务使用promisifyTask(这样它就不会被捕获,并在最后到达捕获点),但我在.settle中使用promisifyTaskAndCatch,这样我就可以轻松地在拒绝后直接绑定和编辑任务的失败信息
  • 只有在主服务器失败后才能到达.catch here。既然我已经完成了所有的次要任务,那么.settle将始终收到已兑现的承诺,因此即使次要任务失败,我也会获得成功
  • 如何编辑此流,以便充分利用这两个方面的优点(.bind.catch用于错误处理,具有一致且清晰的流)

    -----------更新-----------------

    我差点就明白了。我通过删除promisifyTask和Catch并将promisifyTask更改为:

    function promisifyTask(task) {
        var promise = new Promise(function (resolve, reject) {
            task.execute.apply(null, task.args.concat([resolve, reject]));
        });
        promise.bind(task).catch(onTaskFail);
        return promise;
    }
    
    现在语法是一致的,错误层叠通过,我也得到了我的错误报告

    现在唯一的问题是,我不能保证任务的内部捕获会在外部最终捕获之前发生(onFail位于链的末尾),因为这是异步的

    有没有办法回报被抓住的承诺,但仍然失败?我是否可以在不重复.catch中的错误的情况下执行此操作

    现在唯一的问题是,我不能保证任务的内部捕获会在外部最终捕获之前发生(onFail位于链的末尾),因为这是异步的

    实际上您确实有,因为首先调用了
    .catch(onTaskFail)
    ,所以
    onTaskFail
    将在最后一个之前执行。但您是对的,如果最终捕获取决于
    onTaskFail
    所做的事情,那么实际返回对该结果的承诺将更加清晰

    有没有办法回报被抓住的承诺,但仍然失败

    我认为重新抛出
    ing
    reason
    将是最好的选择

    或者您甚至不让它们失败,而是使用并检查任务对象的结果,而不是使用及其
    PromiseInspection
    值。正如您所说,原因保存在任务上,最一致的流程是返回任务对象:

    function onTaskFail(reason){
        this.error = reason; // or so
        return this;
    }
    runTask(primaryAsyncTask).then(function(primResult) {
        return Promise.all(secondaryAsyncTasks.map(function (task) {
            return runTask(task).bind(task).catch(onTaskFail);
        }));
    }).then(function(taskResults) {
        // test for errors in the secondary results
        // and throw them if you want the global onFail
        // else do onSuccess()
    }).catch(onFail);
    
    我是否可以在不重复.catch中的错误的情况下执行此操作

    是的,您还可以
    返回被拒绝的承诺。这可能是一个
    承诺。拒绝(原因)
    ,但更简单的可能是
    返回已经存在的承诺(尽管当前不在
    onTaskFail
    的范围内)。但是,可以在此处使用:

    …
        return promise.bind(task).catch(onTaskFail).return(promise);
    

    我建议您将函数命名为
    runTask
    。“Promisification”是另一回事。你是对的——promisifiedTask的功能实际上类似于“promisifiedTask”。Promisification将返回promisifyTask而不运行它…嗯,还有一件事:不
    承诺。结算
    返回一个始终已解决的承诺,这样您的全局
    onFail
    处理程序将永远看不到被拒绝的次要任务的原因?非常有趣-从捕获中返回任务。我喜欢。关于Promise.all-如果其中任何一个失败,它将立即拒绝,但我想等待所有这些都完成,这就是为什么我使用结算。。。虽然它似乎总是会回报一个兑现的承诺。也许我可以这样做:runTask().then(runAlllTasks//returns promise.settle)。then(function(reasons){return promise.all(reasons)})。then(onSuccess)。catch(onFail)但是当你
    .catch()
    所有错误时,没有一个会失败……如果我使用promise.all对已解决的结果进行处理,如果任何失败,它总是会到达catch,这很好。我将把它作为一个更新发布。我不知道它是否是有意的,但是如果你遵循蓝鸟的来源,它是合乎逻辑的。请参阅:遵循init(这是promiseInspection.all)-promiseInspection不会被强制转换为promiseInspection,并最终在值的直接扫描中输入PromiseArray$\u SettlePromission,其中它询问promiseInspection对象所具有的value.isCompleted()和value.isRejected()。这看起来几乎是故意的,因为在检查中达到这一点的唯一方法似乎是演员是否返回了原始PromiseInspection看起来我在测试这一点时使用了旧版本的bluebird,因为在当前版本上,它不起作用。完成了。
    …
        return promise.bind(task).catch(onTaskFail).return(promise);