用于jQuery承诺重构的用例

时间:2017-03-27 20:57:51

标签: javascript jquery promise refactoring

我想知道是否有可能重构这个伪代码:

function foo() {
   if (condition) {
      return somethingReturningPromise().then(function (data) {
         doSomethingOnSuccess(data);
         return mainFunctionReturningPromise(); // here ...
      }, function () {
         return mainFunctionReturningPromise(); // here ...
      });
   }
   return mainFunctionReturningPromise(); // and here !!!
}

// ... somewhere ...
foo().done(function () {
   // here, mainFunctionReturningPromise successfully resolved
   continueProgram();
});

如您所见,在所有可能的情况下都会调用mainFunctionReturningPromise

  1. 如果符合条件并且somethingReturningPromise()成功
  2. 如果符合条件且somethingReturningPromise()失败
  3. 如果不符合条件
  4. 由于doSomethingOnSuccess(data)提供了特殊处理,我似乎无法找到重构mainFunctionReturningPromise的3次调用的方法。你能吗?

3 个答案:

答案 0 :(得分:1)

寻找可读性和可理解性,我可能会选择这样的东西:

function foo() {
    if (condition) {
        return somethingReturningPromise().then(doSomethingOnSuccess, function(err) {
            // log, but ignore error
            console.log(err);
            return $.when();     // return resolved promise to flip state to resolved in older versions of jQuery
        }).then(mainFunctionReturningPromise);
    } else {
        return mainFunctionReturningPromise();
    }
}

这会在两个地方调用mainFunctionReturningPromise(),但我认为它可以优化以便于遵循逻辑。

如果您只想在一个地方拨打mainFunctionReturningPromise(),可以这样做:

function foo() {
    var p = $.when();   // shortcut to get a resolved promise in jQuery
    if (condition) {
        p = p.then(somethingReturningPromise).then(doSomethingOnSuccess, function(err) {
            // log, but ignore error
            console.log(err);
            return $.when();     // return resolved promise to flip state to resolved in older versions of jQuery
        });
    }
    return p.then(mainFunctionReturningPromise);    
}

jQuery承诺的一个恐怖是使用jQuery 1.x和2.x,为.then()的第二个参数提供处理程序不遵循Promise规范并且不会更改要解析的承诺。您必须显式返回已解析的promise或promise,这些promise最终将解析以使catch处理程序执行其正确的工作。这已在jQuery 3.x中修复。这就是为什么来自catch处理程序的return $.when();来确保promise转换到已解析状态,从而继续使用所有jQuery版本中的其他.then()处理程序。

仅供参考,在这里使用$.when()并没有什么神奇之处。这只是我知道在jQuery中获得解决的承诺的最短路径。比$.Deferred().resolve().promise()更短的方式,这将是jQuery中的教科书方式。

答案 1 :(得分:0)

  • 重构为一个空的catch处理程序,它只是忽略错误,然后将一个mainFunctionReturningPromise调用链接到它
  • 重构else分支也会返回一个空的,已履行的承诺,以便您可以将mainFunctionReturningPromise链接到它

function foo() {
    var p = condition
      ? somethingReturningPromise().then(function(data) {
            doSomethingOnSuccess(data);
            return undefined;
        }, function(err) {
            // ignore error
            return undefined;
        })
      : $.Deferred().resolve(undefined).promise();
    return p.then(mainFunctionReturningPromise);
}

(可以省略undefined s,我只是将它们包括在内以明确mainFunctionReturningPromise参数)

答案 2 :(得分:0)

要使<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input type="button" value="Click" class="item-blog" /> <input type="button" value="Reset" class="item-blog-reset" />出现一次,它必须是承诺链末尾的mainFunctionReturningPromise回调。

为了保证.then()可用,无论.then()的结果如何,您都需要保证承诺。

这可以通过多种方式实现。

一种有趣的方式是将内部代码转换为#34;。从已解决的承诺(jQuery中的if (condition))开始,并在链式$.when()中执行下游决策(if (condition){...})。

.then()