【问题标题】:jQuery deferred object chaining failingjQuery延迟对象链接失败
【发布时间】:2015-09-04 01:50:28
【问题描述】:

为什么这段代码不起作用?

它应该在加载第 2 步之前等待第 1 步加载。目前,第 2 步首先触发。我正在使用 mockjax 来模拟​​ Ajax 调用。

$.mockjax({
    url: "/step1",
    responseTime: [3000, 4000],
    responseText: {
      status: "success",
      text: "Loading Step 1"
    }
});

$.mockjax({
    url: "/step2",
    responseTime: [100, 200],
    responseText: {
      status: "success",
      text: "Loading step 2"
    }
});


$.getJSON("/step1").then( function(response) {
    return  $("#message").html( "message: " + response.text );
})
.then(
    $.getJSON("/step2", function(response) {
            $("#message").html( "message: " + response.text );
    })                
)

【问题讨论】:

  • .then 的参数应该是一个函数。
  • 我在任何地方都没有看到 ES6 承诺?
  • 这与 ES6 Promise 无关。
  • jQuery 承诺是邪恶的。用Promise.cast()杀死他们。

标签: javascript jquery ajax jquery-deferred


【解决方案1】:

getJSON step2 首先触发,因为它具有更短的延迟,并且您有效地同时触发了两个 $.getJSON

试试这个

$.getJSON("/step1").then( function(response) {
    return  $("#message").html( "message: " + response.text );
})
.then(
    function() { // added this
        $.getJSON("/step2", function(response) {
            $("#message").html( "message: " + response.text );
        })         
    } // and added this
)

【讨论】:

    【解决方案2】:

    接受的答案并不完全正确。它并没有真正链接承诺,因为:

    $("#message").html( "message: " + response.text )
    

    是一个同步函数,不返回承诺。因此返回它返回的值不会创建一个承诺链。它适用于本示例,但随着您添加越来越多的 Promise,您会遇到麻烦。

    链接promise的正确方法是返回一个promise:

    someFunction().then(function(){return promise}).then(function(){});
    

    因此,对于您的示例,正​​确的链接方式是:

    $.getJSON("/step1")
    .then( function(response) {
        $("#message").html( "message: " + response.text );
        return $.getJSON("/step2"); // <-------------- return a promise!
    })
    .then(function(response){
        $("#message").html( "message: " + response.text );
    })
    

    【讨论】:

    • 对不起,这个答案是错误的。允许.then() 处理程序运行返回值的同步代码 - 它不必返回承诺。如果这样做,则链中的下一个.then() 处理程序将在同步代码完成时运行。请记住,.then() 处理程序的返回值作为函数参数传递给链中的下一个.then() 处理程序。这不是 .then() 本身的返回值。
    • 这不像对象链接,每个方法都必须返回对象本身(这已经由.then() 方法本身处理)。这与那完全不同。无论.then() 处理程序中运行什么代码,$.mockjax().then(...). then(...) 都运行良好。 .then() 处理程序中运行的内容决定了调用 .then() 回调的时间。如果你返回一个 Promise,那么它会等到该 Promise 解决后再继续这个链。如果您返回一个值,该值只会传递给下一个 .then() 处理程序。
    【解决方案3】:

    更新:根据 cmets,$.when() 在这里是不必要的,应该在合并多个 Promise 时使用。

    我建议使用 when - jsFiddle 示例 here

        $.mockjax({
        url: "/step1",
        responseTime: [3000, 4000],
        responseText: {
          status: "success",
          text: "Loading Step 1"
        }
    });
    
    $.mockjax({
        url: "/step2",
        responseTime: [100, 200],
        responseText: {
          status: "success",
          text: "Loading step 2"
        }
    });
    
    
    $.when($.getJSON("/step1"))
        .then( function(data, textStatus, jqXHR) {
            $("#message").html( "message: " + data.text );
        })
        .then(
            $.getJSON("/step2", function(data, textStatus, jqXHR) {
                $("#message").html( "message: " + data.text );
        })                
    )
    

    【讨论】:

    • 这里没有理由涉及$.when()。这仅在您有多个并行运行的 Promise 并且您想知道所有 Promise 何时完成时才有用。 OP 正在尝试进行串行链接,而不是尝试并行运行请求。
    • 感谢您的指点。您是否有任何链接可以进一步阅读此内容?基于 jQuery $.when() 文档 (api.jquery.com/jquery.when) 的开头,我有点困惑 - 第一部分讨论了传递单个 Deferred 并在其后使用 $.then()。
    • $.when() 传递一个承诺是可行的,没有意义。你可以只做$.getJSON(...).then(...) 所以做$.when($.getJSON(...)).then(...) 没有意义。带有单个 promise 的 $.when() 只是额外的、不必要的代码。 $.when() 的用处在于你有多个承诺。
    猜你喜欢
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多