在 jQuery 中处理来自 $.when 的动态参数

Handling dynamic arguments from $.when in jQuery

我的 requests 数组中有 ajax 个请求。请求的数量可以是 1,2 或 3(无所谓,动态)。

这样的请求:

var ajaxRequest = $.get(ajaxUrl, requestData);

我想像这样处理结果:

$.when.apply($, requests).then(function () {
    $.each(arguments, function (key, value) {
        console.log(value);
        //var response = JSON.parse(value[0]); //It is fail if there is only 1 ajax request
    });
});

问题是arguments

如果只有 1 个请求,则每个请求的值将为

string [the json string, what I want to JSON.parse]
string ['success']
Object [the Ajax request Object]

在这种情况下,参数长度为 3,这将导致以后出现问题。

但是,如果我有 2 或 3 个请求,那么我将返回这样的数组(例如 2 个请求):

Array [json string, 'success', ajax Object],
Array [json string, 'success', ajax Object]

如果三个请求,当然多一个数组。

问题就在这里。我无法检查参数的长度,因为如果我有 3 个请求则为 3,如果我只有一个请求则为 3。

所以我重写了我的脚本:

$.each(arguments, function (key, value) {
    if (typeof value === 'string') {
        var response = JSON.parse(value);
    } else {
        var response = JSON.parse(value[0]);
    }
    $('div[data-id="' + response.productId + '"').find('.dictionaryContainer').find('ul').html(response.html);
});

现在我的问题是:

if (typeof value === 'string') {

即使它很好,迭代也是连续的,也许它可以用标志和 return tures 以某种方式被破解,但我敢打赌,有一些更优雅的解决方案。

有人可以帮我处理吗?

简单的解决方法是自己检查请求的长度并调整迭代的内容,如下所示:

$.when.apply(null, requests).done(function() {
 var arg = (requests.length === 1) ? [arguments] : arguments;
 $.each(arg, function(i, response) {
   console.log(response);
 })
});

像这样fiddle

不幸的是,正如您所发现的那样,$.when 和这种承诺的组合基本上被打破了,因为它的混乱行为取决于您是否将一个或两个以上的参数传递给 $.when .

我建议:

  1. 使用承诺(如果需要,使用 polyfill)和承诺化 $.ajax$.get 等;然后在承诺数组上使用 Promise.all

  2. 实现您自己的 $.whenAll 并不混乱。

以下是两者的粗略版本(仅适用于 $.ajax,您可以自己制作 $.get$.post):

#1 的粗略版本:(注意:创建一个新的、干净的承诺而不是重复使用 $.ajax 的承诺,以便 只是 return 结果 [不是 success 的其他参数] 和 return 带有拒绝的单个对象 [不是 error 的各种离散参数]。)

$.promiseAjax = function(options) {
    return new Promise(function(resolve, reject) {
        options = $.extend({}, {
            success: function(result) {
                resolve(result);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                reject({
                    jqXHR: jqXHR,
                    textStatus: textStatus,
                    errorThrown: errorThrown
                });
            }
        }, options);
        $.ajax(options);
    });
};

用法:

var requests = [];
if (someCondition) {
    requests.push($.promiseAjax({/*...*/}));
}
if (someotherCondition) {
    requests.push($.promiseAjax({/*...*/}));
}
Promise.all(requests).then(function(results) {
    // `results` will reliably be an array of the results, even when
    // there's only one request
});

#2 的粗略版本:

$.whenAll = function(promises) {
    var d = $.Deferred();
    var results = [];
    var counter = promises.length;
    promises.forEach(function(promise, index) {
        promise
            .done(function(result) {
            results[index] = result;
            if (--counter == 0) {
              // All done
                d.resolve(results);
            }
          })
          .fail(function() {
            d.reject(Array.prototype.slice.call(arguments));
          });
    });
    return d.promise();
};

用法:

var requests = [];
if (someCondition) {
    requests.push($.ajax({/*...*/}));
}
if (someotherCondition) {
    requests.push($.ajax({/*...*/}));
}
$.whenAll(requests).then(function(results) {
    // `results` will reliably be an array of the results, even when
    // there's only one request
});