0

I am probably looking for something that is impossible, but anyway let's give it a try. Please consider the following pseudo code that is performing some conditional, remote operation, that executes callback upon completion. But the code in the callback needs to be executed even if remote operation was not neccessary:

if (needsToSave)
{
  performRemoteOperation(operationParameters, function() {
    doSomeCleanup();
    doSomeMoreCleanup();
    setSomeStatus();
  });
}
else
{
    doSomeCleanup();
    doSomeMoreCleanup();
    setSomeStatus();
}

I find this code particularly ugly and unmanageable. It is easy to omit a change done to callback block in relevant unconditional block. There is an obvious solution of wrapping code in some named function, but it isn't anonymous inline code anymore then. :-)

The best I can think of is to wrap whole code in some conditional caller:

function conditionalCall(condition, action, callback)
{
  if (condition)
    action(callback)
  else
    callback()
}

Then my code would fold to:

conditionalCall(needsToSave,
  function(_callback) {
    performRemoteOperation(operationParameters, _callback)
  },
  function()
  {
    doSomeCleanup();
    doSomeMoreCleanup();
    setSomeStatus();
  }
);

...but I am not absolutely sure, whether this is more readable and manageable. Especially when lots of local/remote/callback parameters/closure variables get involved or one needs to "embed" one remote call within another call's callback. I hope there is some better syntax that could be used in such a scenario.

4

2 回答 2

0

这不是一个真正的关闭问题。假设“远程操作”意味着“异步操作”,那么它与处理异步响应有关。

当然,可以(并且通常会)在这种情况下使用匿名函数,但请记住,“匿名函数”不是“闭包”的同义词。忘记(几乎)你在 PHP 中学到的所有东西,这不是词法闭包的一个很好的学习基础。

如果我的假设是正确的,并且我们确实在谈论异步性,那么 jQuery 的 Deferreds/promises 是一个相当简洁的解决方案。

// First make sure performRemoteOperation() returns a promise,
function performRemoteOperation(operationParameters) {
    ...
    return promise;//for example a jqXHR object, as generated by $.ajax() and its shorthand methods.
}

function myFunction(needsToSave) {
    var p = needsToSave ? performRemoteOperation(operationParameters) : $.Deferred.resolve().promise();
    //At this point `p` is either an unresolved promise returned by performRemoteOperation(), or a resolved promise generated in the line above.
    p.done(function() {
        //This function fires when the remote operation successfully completes, or immediately if `needsToSave` was false.
        doSomeCleanup();
        doSomeMoreCleanup();
        setSomeStatus();
    });
    return p;//A promise is returned for good measure, in case further chaining is necessary where myFunction() is called.
}

//Sample calls
myFunction(false);

myFunction(true).then(function() {
        alert("successfully saved");
    }, function() {
        alert("error: something went wrong");
    });

当然,如果您愿意,您可以将代码重构为单个函数,但可以说更容易理解为两个函数,如问题中所示。

于 2013-06-27T15:58:38.237 回答
0

可以简化为:

var finallyFunction = function {
    doSomeCleanup();
    doSomeMoreCleanup();
    setSomeStatus();
}    

if (needsToSave)    
    performRemoteOperation(operationParameters, finallyFunction);
else
    finallyFunction();
于 2013-06-27T13:03:57.020 回答