【问题标题】:Why is my Jquery ajax success handler being called with an array (and not the response object)为什么用数组(而不是响应对象)调用我的 Jquery ajax 成功处理程序
【发布时间】:2013-12-13 13:18:25
【问题描述】:

我有一个函数可以对 Google 电子表格 API 进行两次休息调用。我使用 $.when 来确保在处理来自第二个调用的数据之前处理来自第一个调用的数据。

问题是第一个 ajax 处理程序 (getRealNames) 接收一个 javascript 对象作为其参数,但第二个处理程序 (displayTeams) 接收一个数组,第 0 个元素是我期望得到的对象。

为什么一个得到一个对象而另一个得到一个数组?他们正在调用相同的 rest api。 直到我重构代码以使用延迟而不是回调嵌套,该数组才出现。所以我认为这是一个 jquery 问题而不是电子表格 API 问题。

(见下面的屏幕截图,我已经控制台记录了两个处理程序收到的参数

//this is the function generating the REST requests, I just put it in for completeness
function getWorkSheet(doc_key,sheet){
  return $.get('https://spreadsheets.google.com/feeds/list/'+
    doc_key+'/'+sheet+
    '/private/full?alt=json&access_token=' 
    + googleAPItoken)
    .fail(function(){
      alert("failed to get google doc:"+doc_key+" ,sheet: "+sheet);
    });

  }

 function getRWMTeams() {
    var nameQuery=getWorkSheet(doc_key,1);
    nameQuery.done(getRealNames);

    var repoQuery=getWorkSheet(doc_key,2);

    //the deferred:'namesProcessed' is resolved in getRealNames
    $.when(repoQuery,namesProcessed)
      .done(displayTeams);

  }

【问题讨论】:

  • 可能是因为你将两个延迟对象传递给了when

标签: ajax jquery jquery-deferred google-spreadsheet-api


【解决方案1】:

最终,更仔细阅读 api 文档(http://api.jquery.com/jQuery.when/) 在代码示例中发现了以下注释;

// 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 ]

我已经阅读了第一条评论,并假设参数只是返回数据。第二条评论揭示了我的问题的根源。

【讨论】:

    【解决方案2】:

    尽管这是一个古老的已回答问题,但在 jQuery 进入 Promises/A++ 时代(预计在 2015 年某个时候)之前,它应该得到一个更完整的答案。

    与其他 Promise 库不同,jQuery Promise 可以通过多个值来解决。这让jQuery.when() 的生活有些尴尬。

    文档说:

    传递给 doneCallbacks 的参数为每个 Deferred 提供解析值,并匹配 Deferred 传递给 jQuery.when() 的顺序。

    并继续解释 doneCallback 参数对于不同数量的已解析值的行为 - 这就是它变得有点疯狂的地方:

    • 无值:对应的参数将是undefined
    • 单个值:相应的参数将保存该值
    • 多个值:对应的参数将是这些值的数组

    您看到的是第三种情况 - jQuery.ajax() - datatextStatusjqXHR 返回的三个值 - 捆绑到一个数组中。这在直接使用 jqXHR 承诺时是不可避免的。

    但是,有一个解决方法。如果您安排getRealNames() 包含一个链式.then(),则可以丢弃textStatusXHR,并返回一个仅data 的承诺——因此给出单个值 上述行为。例如:

    function getRealNames() {
        return $.ajax(...)
            .then(function(data, textStatus, jqXHR) {
                return data;
            });
    }
    

    这就是你需要做的,但是你的getRWMTeams()函数也可以被整理,如下:

    function getRWMTeams() {
        var repoQuery = getWorkSheet(doc_key, 2);
        var namesProcessed = getWorkSheet(doc_key, 1).then(getRealNames);
        return $.when(repoQuery, namesProcessed).then(displayTeams);
    }
    

    function getRWMTeams() {
        return $.when(
            getWorkSheet(doc_key, 2), 
            getWorkSheet(doc_key, 1).then(getRealNames)
        ).then(displayTeams);
    }
    

    【讨论】:

      【解决方案3】:

      感谢您提出这个问题,并提供答案。我一直遇到完全相同的问题,并且试图理解“参数是数组”背后的原因一直是一个挑战。

      现在我明白了为什么参数是数组,我注意到只有第一个参数是数组。第二个参数仅包含数据(来自已解析的延迟)。你是否也注意到了这一点?这是一个屏幕截图来解释更多:

      'fields' 和 'defn' 是我在 done 回调中的参数。一个是数组,另一个是对象。我很想知道你对此的看法。

      【讨论】:

      • 我注意到,在作为 $.when() 的参数提供的两个方法中,实际上只有一个方法使用 $.get() 进行了 ajax 调用。这是因为我的代码的编写方式。另一种方法只是使用 $.Deferred() 并返回一个承诺(我的代码会立即解决它)。只有当实际的 XHR 已经生成时,回调参数才可能是一个数组(包含 xhr 详细信息)。
      猜你喜欢
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多