jQuerys jqXHR延迟无法链接$ .when(...)

时间:2017-04-28 21:54:43

标签: javascript jquery promise

我想等待多个承诺得到解决。选择的方法是使用jQuery的$.when()函数来等待所有这些:

let test = $.Deferred();
$.getJSON('test.json')
    .done((content) => {
        test.resolve(content);
    });

$.when(
    test,
    $.when(17)
).done((testContent, value) => {
    console.log('test content: ' + testContent.first);
    console.log('value: ' + value);
});

使用过的测试JSON文件(test.json)如下所示:

{
  "first": "one",
  "second": "two"
}

控制台上的预期和实际输出是:

test content: one
value: 17

但是:(Lo And Behold!)

$.when(
    $.getJSON('test.json'),
    $.when(17)
).done((testContent, value) => {
    console.log('test content: ' + testContent.first);
    console.log('value: ' + value);
});

使用此代码,输出将更改为:

test content: undefined
value: 17

什么?未定义?请注意,代码中唯一的区别是$.getJSON函数直接用作$.when指令中的延迟之一,而不是被提取到单独的延迟。

为什么呢?有什么区别?

在我看来,jqXHR样式延迟与jQuery的$.when函数不是100%兼容。

  • jqXHR deferred正确用于额外承诺" test"
  • 额外的延期"测试"可以在$.when
  • 中使用

为什么这样做,但我不能直接在$.getJSON函数中使用$.when jqXHR对象?

我正在使用jQuery 3.2.1。

更新29.04.2017

我创建了一个fiddle

如您所见,如果我直接在$.when指令中嵌入jqXHR承诺,则此承诺的结果不仅是JSON值,还包括以下数组:

[ JSONValue, statusCode, XHR ]

为什么jqXHR在$.when中的行为有所不同,然后在$.when之外使用?

1 个答案:

答案 0 :(得分:1)

您正在获取一组值,因为jqXHR解析为多个值(通常传递给.done()方法的3个参数)。来自$.when文档:

  

如果Deferred解析为单个值,则相应的参数将保存该值。在Deferred解析为多个值的情况下,相应的参数将是这些值的数组。

因此,您需要索引或解构结果以获得所需的值。

$.when(
    $.getJSON('test.json'),
    $.when(17)
).done(([testContent, textStatus, jqXHR], value) => {
    console.log('test content: ' + testContent.first);
    console.log('value: ' + value);
});

当您使用单独的承诺时,您没有看到这一点,因为您只是使用单个值解析它

(content) => {
    test.resolve(content);
}

如果在解析promise时传递了所有参数,您会看到相同的数组行为:

let test = $.Deferred();
$.getJSON('https://api.myjson.com/bins/bmguh')
  .done((content, status, jqXHR) => {
    test.resolve(content, status, jqXHR);
  });

$.when(
  test,
  $.when(17)
).done((testContent, value) => {
  console.log('Separate promise:', JSON.stringify(testContent));
});

// jqXHR used directly in $.when:
$.when(
  $.getJSON('https://api.myjson.com/bins/bmguh'),
  $.when(17)
).done((testContent, value) => {
  console.log('jqXHR used directly:', JSON.stringify(testContent));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>