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

时间:2013-06-27 12:52:16

标签: callback closures anonymous-function

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

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();
  }
);

...但我不完全确定,这是否更具可读性和可管理性。特别是当涉及大量本地/远程/回调参数/闭包变量或者需要在另一个调用的回调中“嵌入”一个远程调用时。我希望在这种情况下可以使用更好的语法。

2 个答案:

答案 0 :(得分:0)

In可以简化:

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

if (needsToSave)    
    performRemoteOperation(operationParameters, finallyFunction);
else
    finallyFunction();

答案 1 :(得分:0)

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

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

如果我的假设是正确的,而且我们确实在讨论异步性,那么jQuery的延迟/承诺会产生一个相当简洁的解决方案。

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

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