【问题标题】:Jquery Deferreds - second fail being called unexpectedlyJquery Deferreds - 第二次失败被意外调用
【发布时间】:2017-08-13 02:06:21
【问题描述】:

我有一个排序函数,它基本上有两个 REST 步骤 - 步骤 1 和 2。 我正在通过以下方式处理它 - 调用 step1 并为其设置一个失败和一个 then 处理程序,然后进行第二次调用 - step2 具有自己的失败和处理程序。

self.step1()
    .fail(self.onStep1Fail.bind(self))
    .then(self.onStep1Done.bind(self))
    .then(self.step2.bind(self))
    .fail(self.onStep2Fail.bind(self))
    .then(self.onStepDone.bind(self));

我对这个序列的解读是调用了step1,如果失败了,就会调用step1的fail方法。如果step1成功,则依次调用step1Done和step2,然后step2判断是调用step2Fail还是Step2Done。

但由于某种原因,当 step1 失败时,Step1Fail 和 Step2Fail 都会被调用 - 这是意料之外的。有谁知道为什么?另外,我怎样才能改变它以实现我想要的 - 只有在 step2 实际执行后才调用 step2Fail。

我使用以下方法实现了这一点:

    var handled = false;

    function onCatch(handler) {
        if (!handled) {
            handled = true;
            handler.call(self, Array.prototype.slice.call(window.Array.apply(null, arguments), 1));
        }
        return $.Deferred().reject().promise();
    }

    self.step1()
        .catch(onCatch.bind(self, self.step1Fail))
        .then(self.step1Done.bind(self))
        .then(self.step2.bind(self))
        .catch(onCatch.bind(self, self.step2Fail))
        .then(self.step2Done.bind(self));

但我正在寻找是否有更简单的方法。

【问题讨论】:

    标签: javascript jquery promise jquery-deferred deferred


    【解决方案1】:

    fail 只是附加一个失败处理程序,没有任何回调链接,它返回延迟的输入。

    step1() 失败时,整个链都会这样做,即链中的每个承诺都会被拒绝。并且每个承诺的失败处理程序都会被触发,在你的情况下onStep1FailonStep2Fail

    如果您希望仅在执行 step2 时调用 onStep2… 处理程序,请不要将它们放在整个链上:

    self.step1()
    .fail(self.onStep1Fail.bind(self))
    .then(self.onStep1Done.bind(self))
    .then(function(step1doneResult) {
        return self.step2(step1doneResult)
        .fail(self.onStep2Fail.bind(self))
        .then(self.onStepDone.bind(self));
    });
    

    我建议完全不要使用fail 方法,因为它缺乏链接。而是使用then的第二个参数:

    self.step1()
    .then(self.onStep1Done.bind(self), self.onStep1Fail.bind(self))
    .then(function(step1handlerResult) {
        return self.step2(step1handlerResult)
        .then(self.onStepDone.bind(self), self.onStep2Fail.bind(self));
    });
    

    【讨论】:

    • 它并没有变得不可读,promise 的强大之处在于它们是线性链接的,而不是像回调那样嵌套。当然,如果你想在每一步上区分成功/失败,那就让你像 if/else 分支一样嵌套 - 而嵌套 blocks 在结构化编程中是完全自然的。
    • 谢谢!所以到时候就可以期待了!我试图尽可能避免嵌套,因为它会导致代码不可读,特别是如果有更多的步骤正在进行中。另外,我通常更喜欢 catch 而不是失败。
    • 是的,catch(从 jQuery 3 开始可用)很好,尽管它与 fail 根本不同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    • 2021-04-02
    • 2010-12-21
    • 1970-01-01
    相关资源
    最近更新 更多