Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将带有回调的方法转换为返回带有清除的承诺的方法_Javascript_Callback_Promise_Q - Fatal编程技术网

Javascript 将带有回调的方法转换为返回带有清除的承诺的方法

Javascript 将带有回调的方法转换为返回带有清除的承诺的方法,javascript,callback,promise,q,Javascript,Callback,Promise,Q,我正在尝试编写一个函数,该函数执行异步任务并返回承诺,同时确保在完成任何回调后进行清理。然而,要做到这一点,我似乎需要提前知道回调,以便确保它在清理之前发生 目前,该函数的总体结构如下所示: function doSomethingWithResourceAsync(someParameter, usePreparedResourceCb) { var resource = acquireResource(someParameter); return prepareResourc

我正在尝试编写一个函数,该函数执行异步任务并返回承诺,同时确保在完成任何回调后进行清理。然而,要做到这一点,我似乎需要提前知道回调,以便确保它在清理之前发生

目前,该函数的总体结构如下所示:

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

    function doCleanup() {
        releaseResource(resource);
    }
}
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);
称之为,我会这样做:

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

function myCallback(proxyObj) {
    return doMagicAsync(proxyObj);
}
这是我能让它工作的唯一方法

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

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

    function doCleanup() {
        releaseResource(resource);
    }
}
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将被那些不一定知道异步方法的复杂性的用户所使用,因此我想尽可能地隐藏它们。

您所拥有的是。你自己想出来的道具:)

“传递”回调是必要的,因为它创建了一个有效启用清理的范围。通过返回承诺,您将知道回调是如何“完成”的。事实上,你需要一个范围是基本的,因为它是什么,以及。。。确定清理范围。通过作用域(RAII)将资源分配绑定到实例化是一种非常有用的技术

我会这样做:

function withResource(handler){
    return acquireResource(). // important to return to chain, like your code
           then(handler).finally(cleanup);
}
这实际上就是你已经拥有的


正如评论所暗示的那样,bluebird的
使用
是一个非常有用的抽象,它返回的处理器为您提供了大量清理和清理大量类型错误的能力。我强烈推荐它(尽管我显然有偏见)。

使用蓝鸟而不是Q,你可以使用
使用
:这在将来可能非常有用,谢谢你向我指出。很好地自己找到了这个模式:)你能扩展你的例子,说明需要清理的地方吗,它需要如何等待
回调
(或者:如果过早清理,
回调
中有什么不起作用)?有一种模式可以解决这个问题,但我需要详细说明您的问题。@Bergi:这是Node应用程序的一部分。在某些情况下,它只是用于日志记录。在其他实例中,它用于启动子进程(和日志记录)。在我的用例中,子进程必须运行才能使回调工作。当我提到传递回调时,我指的不是处理程序(在我的示例中是
cb()
函数),而是
doCleanup()
函数。我不能完全相信所有调用代码都会记得总是在处理程序中调用cleanup函数。但很高兴看到你同意我的决定。回想起来,我认为这确实是最干净的方法。实际函数的名称已经暗示它将从头到尾做一些事情。说“完成这项工作,然后再做这项工作”并期望它能工作是没有意义的。确切地说,你必须以某种方式定义“开始”和“完成”,你也可以用一个范围来做,这意味着你永远不会忘记自己做清理。这在许多编程语言中都是基础,很有趣的是,看到一些语言在其核心中集成了该功能,比如C#的
async使用
方案和Python 3.5的
async使用
。在JavaScript中使用这种资源管理是很好的,但遗憾的是,我认为我们还没有做到这一点——当async/await明年登陆时(希望如此),我们将有更令人信服的能力:)