2015-09-07 71 views
3

我正在尝试编写一个函数,该函数执行异步任务并返回承诺,同时确保在任何回调完成后发生清理。但是为了做到这一点,我似乎需要提前知道回调,以便在发生清理之前确保它发生。将回调方法转换为使用清理返回承诺的方法

目前,该功能的总体结构是这样的:

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将被不需要知道异步方法的复杂性的用户使用,因此我想尽可能隐藏这些API。

+0

用Bluebird代替Q,你可以使用'using':https://github.com/petkaantonov/bluebird/blob/master/API.md#resource-management –

+0

这可能对未来非常有用,谢谢为我指出这一点。 –

+0

很好搞清楚这个模式在你自己:) –

回答

3

你有什么是disposer pattern。道具中是必要,因为它创建了一个范围这就是有效地实现清理认定它在你自己:)

“传递”回调。你会知道回调是如何通过它返回一个承诺“完成”的。你需要一个范围的事实是基本,因为它是什么... 范围的清理。将资源分配绑定到通过范围实例化(RAII)是一种有用的技巧。

我会做这样的事情:

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

这是有效的你已经拥有。

正如评论所示,蓝鸟的using是一个非常有用的抽象,它返回的垃圾处理器给你很多清理和清理很多类型的错误的权力。我强烈推荐它(尽管我显然有偏见)。

+0

当我提到传递回调时,我没有提到处理函数(在我的例子中是'cb()'函数),而是'doCleanup()'函数。我不能完全相信所有调用代码都会记得总是在处理程序中调用清除函数。但很高兴看到你同意我在这里的决定。回想起来,我认为这确实是最干净的方式。实际功能的名称已经暗示它将从头到尾做一些事情。说这样做完成,然后做到这一点,并期望它有效,没有任何意义。 –

+0

准确地说,您必须以某种方式定义“开始”和“完成”,您也可以用范围来完成,这意味着您永远不会忘记自己进行清理。这是很多编程语言的基础,看到语言将设施集成到他们的核心中很有趣 - 比如C#的异步使用提议和Python 3.5的异步使用。在JavaScript中进行这种资源管理会很棒,但可惜我并不认为我们已经到了这一步了 - 当异步/等待明年登陆时(希望)我们将拥有更多令人信服的力量:) –