将带回调的方法转换为返回带有清除的promise的方法

时间:2015-09-07 06:07:21

标签: javascript callback promise q

我试图编写一个执行异步任务的函数并返回一个promise,同时确保在完成任何回调后进行清理。但是要做到这一点,我似乎需要提前知道回调,以便我可以确保它在清理发生之前发生。

目前,该函数的一般结构如下所示:

function doSomethingWithResourceAsync(someParameter, usePreparedResourceCb) {
    var resource = acquireResource(someParameter);
    return prepareResourceAsync(resource)
        .then(usePreparedResourceCb)
        .finally(doCleanup);

    function doCleanup() {
        releaseResource(resource);
    }
}

要打电话,我会这样做:

doSomethingWithResourceAsync(myParameter, myCallback)
    .then(andSoOn);

function myCallback(proxyObj) {
    return doMagicAsync(proxyObj);
}

这是我能让它发挥作用的唯一方法。

但是,我想以一种可以链接我的回调而不必传递清理回调的方式来编写它。所以我想这样称呼它:

function doSomethingWithResourceHopefullyAsync(myParameter) {
    var resource = acquireResource(someParameter);
    return prepareResourceAsync(resource)
        .finally(doCleanup); // uh oh

    function doCleanup() {
        releaseResource(resource);
    }
}

doSomethingWithResourceHopefullyAsync(myParameter)
    .then(myCallback) // too bad, already cleaned up
    .then(andSoOn);

然而,这并不起作用,因为在myCallback获得控制权之前进行了清理并且搞砸了。

如果可能,我如何构建我的方法来实现我的目标?或者我能为这种情况做得最好吗?

我有一种感觉,我可以使用延迟来实现我的目标,但我不知道如何设置它以使这项工作。

我试图开发的API将被那些不一定知道异步方法的复杂性的用户所使用,所以我想尽可能地隐藏它。

1 个答案:

答案 0 :(得分:3)

你拥有的是disposer pattern。道具可以自己解决:)

"传递"回调是必要的,因为它创建了一个范围,它有效地启用了清理。你知道回调是如何完成的"通过它返回一个承诺。你需要一个范围的事实是基础,因为它是什么...... 范围清理。通过范围(RAII)将资源分配绑定到实例化对于您正在进行的操作是一种有用的技术。

我会做类似的事情:

function withResource(handler){
    return acquireResource(). // important to return to chain, like your code
           then(handler).finally(cleanup);
}

这实际上是你已经拥有的。

正如评论所暗示的那样,蓝鸟的using是一个非常有用的抽象,它会返回处理器,它为你提供了很大的清理能力并清理了很多类型的错误。我强烈推荐它(虽然我明显有偏见)。