【问题标题】:Cancel a promise from the 'then'取消“then”的承诺
【发布时间】:2015-01-23 19:23:04
【问题描述】:

我刚刚切换到 Promise,我确定我做错了什么,但我不知道是什么。 在下面的代码中,如果 _getDevice() 返回 null (它是 mongodb.findOneAsync() 在引擎盖下),我想取消承诺。

从我的角度来看,如果 _getDevice 返回 null,则应取消承诺,我应该会看到“CANCEL REPLY”日志。但相反,我得到了“保存回复”日志。

我正在使用 bluebird 库。

var promise = Promise.props({
    device: _getDevice(event.deviceId),
    events: _getEvents(event.deviceId, event.date)
}).cancellable();

promise.then(function (result) {
    if (! result.device) {
        return promise.cancel()
    }

    var device = new Device(result.device);
    var events = result.events;

    // ...

    return db.collection(collections.devices).saveAsync(device.toMongoDocument());
}).then(function () {
    console.log('SAVE REPLY');
    return req.reply(null);
}).catch(Promise.CancellationError, function (err) {
    console.log('CANCEL REPLY')
    return req.reply(null);
}).catch(function (error) {
    return req.reply(error);
});

【问题讨论】:

    标签: promise bluebird cancellation


    【解决方案1】:

    您不能从then 回调中取消承诺,因为该回调的执行意味着承诺已被解决。之后无法更改状态。

    您可能想要做的是从处理程序中抛出一个错误,从而导致从then() 返回的新承诺被拒绝。

    你甚至可以在两个 Promise 加入之前这样做,这样当 getDevice Promise 失败时,getEvents Promise 就会被取消:

    Promise.props({
        device: _getDevice(event.deviceId).then(function(device) {
            if (!device)
                throw new Promise.CancellationError(); // probably there's a better error type
            else
                return new Device(device);
        },
        events: _getEvents(event.deviceId, event.date) // assuming it is cancellable
    }).then(function (result) {
        var device = result.device;
        var events = result.events;
    
        // ...
    
        return db.collection(collections.devices).saveAsync(device.toMongoDocument());
    }).then(function () {
        console.log('SAVE REPLY');
        return req.reply(null);
    }).catch(Promise.CancellationError, function (err) {
        console.log('CANCEL REPLY')
        return req.reply(null);
    }).catch(function (error) {
        return req.reply(error);
    });
    

    【讨论】:

    • 这是一个很好的答案。谢谢!
    【解决方案2】:

    我认为接受的答案并不完全正确;参见Cancelling Long Promise Chains——可以从then() 中取消承诺。但是我不确定原始问题的确切问题是什么(行为并未真正描述)。

    尝试将.cancellable() 也放在第二个承诺的末尾。

    【讨论】:

    • 当然你可以从then回调中取消任意的promise,但是promise不能从它自己的回调中取消自己,这是OP试图做的。
    • 好吧,我想我没有看到区别。谢谢。
    • 值得一提的是整个取消 API 正在考虑重写:github.com/petkaantonov/bluebird/issues/415
    猜你喜欢
    • 2021-10-17
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 2016-11-25
    • 2016-03-09
    • 2020-07-01
    • 1970-01-01
    相关资源
    最近更新 更多