$ .when.apply根据输入数组的长度返回具有不同结构的结果

时间:2016-04-16 17:31:39

标签: javascript promise

我正在尝试编写一个通用代码来获取promises的结果。请参阅示例代码。

https://jsfiddle.net/f995r4ue/

var testUri = 'https://fiddle.jshell.net/robots.txt';

var promises = [];
promises.push($.get(testUri));
$.when.apply($, promises).then(function() {
   // arguments is array of objects
   console.log(arguments);
});

var promises = [];
promises.push($.get(testUri));
promises.push($.get(testUri));
$.when.apply($, promises).then(function() {
   // arguments is array of arrays
   console.log(arguments);
});

如代码中所述,如果输入数组只有一个promise,则结果结构与其他情况不同。

我做错了吗?

2 个答案:

答案 0 :(得分:1)

这是jQuery Ajax承诺工作的疯狂方式以及jQuery决定如何实现$.when()的副产品。这有点奇怪的行为偶尔有用,但不足以经常让你疯狂。行为的不一致性不是一个好的基本设计,我相信jQuery计划在jQuery 3.0中清除它,因为它们应该与ES6标准的promise规范兼容(这种方式并不奇怪)。

这是发生了什么。一个jQuery Ajax承诺解析了三个值(完全不符合promise)。如果您只将其中一个承诺传递给$.when(),那么$.when()直接通过该承诺(根据文档,它甚至不会创建新承诺)。因此,当该Ajax承诺解析并调用它的.then()处理程序时,它将以原始承诺的方式调用.then()处理程序,该处理程序具有三个单独的参数。如果在这种情况下查看arguments附加到.then()处理程序的$.when()对象,您将看到三个不连续的参数。

但是,如果您将多个承诺传递给$.when(),那么它会创建一个新的超集承诺,监控您传递的所有承诺。如果每个基础promise都使用多个值解析,则该超集promise将把每个单独的promise的参数放入其自己的数组中,并将每个单独的数组作为单独的参数传递给.then()处理程序。如果查看arguments对象,您将看到一个数组数组。如果每个潜在的承诺只用一个值解决,那么每个参数就只是那个值 - 另一个不一致点。

我期待jQuery 3.0说它将遵循承诺规范,它将停止做这种奇怪的事情。

以下是jQuery doc中的示例:

// single promise passed to $.when()
// arguments to `$.when()` are identical to what that single promise would
//    have sent to its .then() handler which for a jQuery Ajax
//    function is three separate arguments
$.when( $.ajax( "test.aspx" ) ).then(function( data, textStatus, jqXHR ) {
  alert( jqXHR.status ); // Alerts 200
});

// multiple promises passed to $.when()
// Each argument to .then() is an array of arguments
$.when( $.ajax( "/page1.php" ), $.ajax( "/page2.php" ) ).then(function( a1, a2 ) {
  // a1 and a2 are arguments resolved for the page1 and page2 ajax requests, respectively.
  // Each argument is an array with the following structure: [ data, statusText, jqXHR ]
  var data = a1[ 0 ] + a2[ 0 ]; // a1[ 0 ] = "Whip", a2[ 0 ] = " It"
  if ( /Whip It/.test( data ) ) {
    alert( "We got what we came for!" );
  }
});

所以,是的,行为是一致的。如果您不知道期望有多少参数,则必须测试您决定如何处理它的类型。

所以,这里发生的非标准和不一致的事情是:

  1. jQuery Ajax调用使用三个单独的参数解析(promise标准表示只获得一个参数,如果要返回多个值,则返回数组或对象)
  2. 如果传递一个承诺或多个承诺,
  3. $.when()的行为会有所不同。
  4. 如果传递给它的基础承诺使用单个值或多个值解析,则
  5. $.when()的行为会有所不同。
  6. ES6承诺世界要简单得多,因为承诺永远不会解决多个值。如果程序员想要回传多个值,那么你就可以解决一个数组或一个对象(就promise而言仍然是一个单独的值)并且jQuery正在做的这些不一致的恶作剧都不能完成。你总是知道你将在Promise.all()得到什么 - 你总能得到一系列结果。

答案 1 :(得分:-1)

Multiple返回2的原因是数组中有2个元素(2个push操作的结果)。每个数组元素(promises [0]和promises [1])包含3个与Single实例相等的元素。