有条件调用的匿名函数的良好语法



我可能在寻找一些不可能的东西,但无论如何,让我们试一试。请考虑下面的伪代码,它正在执行一些有条件的远程操作,并在完成后执行回调。但是回调中的代码需要执行,即使不需要远程操作:

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

我发现这个代码特别难看而且难以管理。在相关的无条件块中,很容易省略对回调块所做的更改。有一个明显的解决方案可以在一些命名函数中包装代码,但它不再是匿名内联代码。:-)

我能想到的最好的方法是将整个代码封装在某个条件调用程序中:

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

然后我的代码会折叠为:

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

但我不完全确定这是否更可读和更易于管理。特别是当涉及大量本地/远程/回调参数/闭包变量时,或者需要将一个远程调用"嵌入"到另一个调用的回调中时。我希望在这样的场景中可以使用一些更好的语法。

In可以简化为:

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

这并不是一个真正的闭包问题。假设"远程操作"的意思是"异步操作",那么它就是处理异步响应。

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

如果我的假设是正确的,并且我们确实在谈论异步性,那么jQuery的Deferreds/promise提供了一个相当巧妙的解决方案。

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

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

最新更新