【问题标题】:jQuery.Deferred().then, how to resolve with multiple parametersjQuery.Deferred().then,如何用多个参数解析
【发布时间】:2014-07-11 18:08:21
【问题描述】:

所以我的 API 期望当一个特定的延迟被解决时,它会获得 2 个参数。

fn().done(function(arg1, arg2) {
  console.log(arg1, arg2);
}).fail(function(err) {
  console.error(err);
});

现在涉及到上面的fn函数,它需要先等待其他一些deferred返回才能解析。

function other() {
  // stubbed out to always resolve
  return $.Deferred().resolve().promise();
}

function fn() {
  return other().then(function() {
    return [1, 2];
  });
}

但这不起作用,因为arg1 将作为[1, 2]arg2 将是undefined。我不知道如何从Deferred.then() 第一个成功过滤函数参数返回一些东西,以便生成的管道延迟解析与多个参数。

我当然可以这样做:

function fn() {
  var done = $.Deferred();
  other().done(function(){
    done.resolve(1, 2);
  }).fail(function(){
    done.reject.apply(done, arguments);
  });
  return done.promise();
}

但这并不像使用 .then() 那样优雅,我现在每次都需要担心否定失败案例 API,即使我知道我只是通过管道传递被拒绝的状态。

是的,我也可以更改 fn() api 以使用数组解析,但我真的希望有一个优雅的解决方案。

【问题讨论】:

  • 第二种方式没那么短,但是调用resolve带2个参数才是正确的传递方式。
  • @TrueBlueAussie 所以我猜你是说答案是没有办法使用then() 函数做我想做的事?
  • 你可以返回一个具有多个属性的匿名对象,这比数组略好?例如return {one: 1, two: 2};
  • @TrueBlueAussie 感谢您的建议,我想我将更改我的 API 以期望这样的对象,因为我讨厌必须处理完成/拒绝状态,我更喜欢使用 @ 987654335@模式

标签: jquery deferred


【解决方案1】:

您必须调用 resolve()reject() 才能传递多个参数。

.then() 不包括任何用于“传播”返回集合的机制。它只会将集合作为第一个参数保持不变。

但是,它将与返回的Deferred 或承诺进行交互。来自paragraph starting with "As of jQuery 1.8"

这些过滤器函数可以返回一个新值以传递给 promise 的 .done() 或 .fail() 回调,或者 它们可以返回另一个可观察对象(Deferred、Promise 等),该对象将传递其已解决/拒绝承诺回调的状态和值

因此,您可以使用other() 的示例作为fn() 的基础,以使其与另一个Deferred() 保持相当简洁:

function fn() {
    return other().then(function () {
        return $.Deferred().resolve(1, 2).promise();
    });
}

fn().then(function (a, b) {
    console.log(arguments.length, a, b); // 2 1 2
});

http://jsfiddle.net/cqac2/

【讨论】:

  • 这看起来很奇怪,fn().done(function(a){console.log(a)}) 然后会将a 记录为一个承诺对象。
  • @codefactor A Deferred() 或 promise 是 .then() 的一个例外,它不会直接传递。它将把它创建的 Promise 绑定到提供给它的 Promise 上。文档中的示例:chaining Ajax requests.
  • 真的吗?太棒了,这就是我要找的!
  • @Jonathan:我对此还很陌生(可能会被误解),但在您的代码示例中调用promise() 不是多余的,因为只有承诺才能看到then() 方法,哪个(我想)不会尝试解决或拒绝它?
  • @Mac 是的,这可能是多余的。即使.then() 试图解决或拒绝延迟,这两种方法在状态设置后都会变为无操作(不再是pending)。
【解决方案2】:

传递给 then 的回调可以返回一个带有 2 个参数的新 $.Deferred,如下所示:

function other() {
  // stubbed out to always resolve
  return $.Deferred().resolve().promise();
}

function fn() {
  return other().then(function() {
    return $.Deferred().resolve(1, 2).promise();
  });
}

【讨论】:

    【解决方案3】:

    在 ES6 中,您可以使用 $.when() 中的扩展运算符和与 .done(//syntax) 链接的成功函数传递可变数量的参数

    $.when(...deferreds).done(
        function (...deferreds) {
            deferreds.forEach(el => {
                console.log("resolved result", el[0].result);
            })
        }).then(function () {
            console.log("do something else");
        });
    

    【讨论】:

      猜你喜欢
      • 2012-02-07
      • 1970-01-01
      • 2021-10-25
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-10
      相关资源
      最近更新 更多