取消'然后'

时间:2014-11-25 17:09:13

标签: promise bluebird cancellation

我只是转而接受承诺,我确定我遇到了问题,但我无法弄清楚是什么。 在下面的代码中,如果_getDevice()返回null(它是引擎盖下的mongodb.findOneAsync()),我想取消这个承诺。

从我的角度来看,如果_getDevice返回null,那么应该取消承诺,我应该看到' CANCEL REPLY'登录。但相反,我得到了“保存回复”#39;登录。

我正在使用蓝鸟图书馆。

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);
});

2 个答案:

答案 0 :(得分:4)

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

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

您甚至可以在加入两个promise之前执行此操作,以便getEvents承诺在getDevice承诺失败时取消:

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);
});

答案 1 :(得分:0)

我不认为接受的答案是完全正确的;请参阅Cancelling Long Promise Chains - 可以取消then()内的承诺。但是我不确定原问题到底是什么问题(行为没有真正描述过)。

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