Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将延迟的数组传递给$.when()_Javascript_Jquery_Argument Passing_Jquery Deferred_.when - Fatal编程技术网

Javascript 将延迟的数组传递给$.when()

Javascript 将延迟的数组传递给$.when(),javascript,jquery,argument-passing,jquery-deferred,.when,Javascript,Jquery,Argument Passing,Jquery Deferred,.when,下面是一个人为的例子: HTML: JavaScript: function getSomeDeferredStuff() { var deferreds = []; var i = 1; for (i = 1; i <= 10; i++) { var count = i; deferreds.push( $.post('/echo/html/', { html: "<p>Tas

下面是一个人为的例子:

HTML:

JavaScript:

function getSomeDeferredStuff() {
    var deferreds = [];

    var i = 1;
    for (i = 1; i <= 10; i++) {
        var count = i;

        deferreds.push(
        $.post('/echo/html/', {
            html: "<p>Task #" + count + " complete.",
            delay: count
        }).success(function(data) {
            $("div").append(data);
        }));
    }

    return deferreds;
}

$(function() {
    $("a").click(function() {
        var deferreds = getSomeDeferredStuff();

        $.when(deferreds).done(function() {
            $("div").append("<p>All done!</p>");
        });
    });
});
我要把一切都做完!在所有延迟任务完成后显示,但$.when似乎不知道如何处理延迟对象数组。全部完成!首先发生,因为数组不是延迟对象,所以jQuery继续并假设它刚刚完成


我知道可以将对象传递到函数中,如$。WhenFerred1、deferred2、…、deferredX,但不知道在我试图解决的实际问题中执行时会有多少个延迟对象。

要将值数组传递给任何通常希望它们是单独参数的函数,请使用function.prototype.apply,因此,在这种情况下,您需要:

$.when.apply($, my_array).then( ___ );

在ES6中,您可以使用。。。相反:

在这两种情况下,由于您不太可能事先知道.then处理程序需要多少形式参数,因此该处理程序需要处理arguments数组以检索每个承诺的结果。

您可以对数组应用when方法:

var arr = [ /* Deferred objects */ ];

$.when.apply($, arr);

以上解决方法谢谢!不要正确地解决返回提供给延迟解析方法的对象的问题,因为jQuery使用单个参数而不是数组调用done和fail回调。这意味着我们必须使用arguments伪数组来获取延迟数组返回的所有已解析/拒绝的对象,这很难看:

$.when.apply$,deferreds.then函数{ var objects=arguments;//作为伪数组的已解析对象数组 ... }; 因为我们传递了一系列延迟,所以返回一系列结果会很好。如果能得到一个实际数组而不是伪数组,那么我们就可以使用array.sort之类的方法

以下是一个受when.js的when.all方法启发的解决方案,该方法解决了以下问题:

//放在脚本环境中的某个地方 如果jQuery.when.all的类型==“未定义”{ jQuery.when.all=函数延迟{ 返回$.Deferredfunction def{ $.when.applyjQuery,deferreds.then //调用函数将接收长度为N的数组,其中N是 //传递给when.all的延迟对象已成功。该数组中的每个元素都将 //它本身是一个由3个对象组成的数组,对应于传递给jqXHR.done的参数: //数据,文本状态,jqXHR 作用{ var arrayThis,arrayArguments; 如果Array.isArraythis{ arrayThis=这个; arrayArguments=参数; } 否则{ arrayThis=[这个]; arrayArguments=[参数]; } def.resolveWitharrayThis[Array.prototype.slice.callarrayArguments]; }, //调用函数将接收长度为N的数组,其中N是 //传递给when.all的延迟对象失败。该数组中的每个元素都将 //它本身是一个由3个对象组成的数组,对应于传递给jqXHR.fail的参数: //jqXHR,textStatus,errorboorn 作用{ var arrayThis,arrayArguments; 如果Array.isArraythis{ arrayThis=这个; arrayArguments=参数; } 否则{ arrayThis=[这个]; arrayArguments=[参数]; } def.rejectWitharrayThis[Array.prototype.slice.CallArrayArrayGuments]; }; }; } } 现在,您只需传入一个延迟/承诺数组,并在回调中返回一个已解析/拒绝对象数组,如下所示:

$.when.all(deferreds).then(function(objects) {
    console.log("Resolved objects:", objects);
});

如果您使用的是angularJS或Q promise库的一些变体,那么您就有了一个.all方法来解决这个确切的问题

var savePromises = [];
angular.forEach(models, function(model){
  savePromises.push(
    model.saveToServer()
  )
});

$q.all(savePromises).then(
  function success(results){...},
  function failed(results){...}
);
请参阅完整的API:


作为一个简单的替代方案,它不需要$.when.apply或数组,您可以使用以下模式为多个并行承诺生成单个承诺:

promise = $.when(promise, anotherPromise);
e、 g

笔记: 在看到有人使用promise=promise.thennewpromise按顺序链接承诺后,我发现了这个问题 缺点是它会在幕后创建额外的promise对象,并且在最后传递的任何参数都不是很有用,因为它们嵌套在其他对象中。为了你想要的东西,虽然它很短很简单。 好处是它不需要阵列或阵列管理。
在调用多个并行AJAX调用时,有两个选项用于处理相应的响应

使用同步AJAX调用/一个接一个/不推荐 使用Promissions的数组,它接受Promissions及其回调。当所有Promissions都成功返回并带有相应的响应时,将调用done。 范例

functi 论资本性{ 返回$.ajax{ 网址:'https://restcountries.eu/rest/v1/capital/"资本,, 成功:功能响应{ }, 错误:functionresponse{ 控制台日志错误 } }; } $function{ var capitalCities=[‘德里’、‘北京’、‘华盛顿’、‘东京’、‘伦敦’]; $‘资本’。文本资本; 函数getCountryCapitals{//执行多个并行ajax请求 var承诺=[];
forvar i=0,l=capitalCities.length;i我想用$提出另一个方案。每个:

我们可能需要声明ajax函数,如:

function ajaxFn(someData) {
    this.someData = someData;
    var that = this;
    return function () {
        var promise = $.Deferred();
        $.ajax({
            method: "POST",
            url: "url",
            data: that.someData,
            success: function(data) {
                promise.resolve(data);
            },
            error: function(data) {
                promise.reject(data);
            }
        })
        return promise;
    }
}
我们使用ajax创建要发送的函数数组的代码部分:

var arrayOfFn = [];
for (var i = 0; i < someDataArray.length; i++) {
    var ajaxFnForArray = new ajaxFn(someDataArray[i]);
    arrayOfFn.push(ajaxFnForArray);
}

如果您正在传输并且可以访问ES6,那么可以使用spread语法,该语法专门将对象的每个iterable项作为离散参数应用,就像$。需要时那样

$.when(...deferreds).done(() => {
    // do stuff
});

我有一个非常类似的例子,我在一个each循环中发布,然后根据从ajax接收到的数字在一些字段中设置html标记。然后我需要对这些字段现在更新的值进行求和,并将其放在一个total字段中

因此,问题是我试图对所有数字进行求和,但异步ajax调用尚未返回任何数据。我需要在几个函数中完成此功能,以便能够重用代码。我的外部函数等待数据,然后再使用完全更新的DOM执行一些操作

    // 1st
    function Outer() {
        var deferreds = GetAllData();

        $.when.apply($, deferreds).done(function () {
            // now you can do whatever you want with the updated page
        });
    }

    // 2nd
    function GetAllData() {
        var deferreds = [];
        $('.calculatedField').each(function (data) {
            deferreds.push(GetIndividualData($(this)));
        });
        return deferreds;
    }

    // 3rd
    function GetIndividualData(item) {
        var def = new $.Deferred();
        $.post('@Url.Action("GetData")', function (data) {
            item.html(data.valueFromAjax);
            def.resolve(data);
        });
        return def;
    }

这真是太棒了。我很惊讶我没能通过谷歌找到这么简单的更改!那是因为它是一个通用方法,不特定于$。当-f.applyctx时,我的_数组将用这个==ctx调用f,并将参数设置为我的_数组的内容。@Alnitak:考虑到这个方法有多长时间,我有点不好意思不知道我现在一直在写JavaScript!FWIW,Eli在回答一个更早期的问题时,讨论了将$vs null作为第一个参数,其中的链接值得一读。不过,在这种特殊情况下,这并不重要。@Alnitak:是的,但是$的键入比null少,并且当$发生变化时,您是安全的。当实现发生变化时,这种情况不太可能发生,但是为什么不在默认情况下保持不变呢?我确实看到了这个问题,但我想,这个问题中所有额外的细节都让我的问题的答案飞到了我的头上。@adamjford,如果这能让你感觉更好的话,我发现你的问题更容易理解,首先是在我特定的谷歌搜索中找到了这个确切的问题。@帕特里奇:很高兴听到它帮助了你!这是一个很好的答案,但我不清楚这是如何应用于原始问题中的示例的。在查阅了链接问题后,很明显,行$.WhenFerreds.donefunction{应该简单地更改为$.when.apply$,deferreds.donefunction{.对吗?这完全不相关。@BenjaminGruenbaum怎么会这样?所有javascript promise库都共享一个类似的API,显示不同的实现没有什么错。我来到这个页面是为了寻找angular的答案,我怀疑许多其他用户会来到这个页面,而不一定是在只使用jquery的环境中。也就是说,因为jQuery的承诺不共享此API,所以这完全不适合作为堆栈溢出的答案-Angular也有类似的答案,您可以在那里询问。更不用说,您应该在这里映射,但很好。相关:为下面这个非常老的问题添加了一个新的、更简单的答案。您不需要使用数组或$.when.ap完全可以得到相同的结果。回滚问题主题,因为它太具体了,这不仅仅是一个AJAX问题如果我错了请纠正我,但是您的方法实际上是嵌套$.when$.when$.when…所以如果有10次迭代,您将递归地嵌套10个级别。这似乎不是非常并行,因为您必须等待每个级别l在返回子级的嵌套承诺之前返回它自己的承诺-我认为接受答案中的数组方法更干净,因为它使用了$.when方法中内置的灵活参数行为。@AnthonyMcLin:这是为了提供一种更简单的编码替代方法,而不是更好的性能,这在大多数as中是可以忽略的ync编码,就像链接一样,然后以类似的方式调用。使用$.when时的行为是并行的,而不是链接的。请尝试一下,然后扔掉一个有用的替代方法,因为它确实有效:@Alnitak:Horses for courses。你当然有权发表意见,但你自己显然没有使用过。我个人的意见是bas这项技术的实际用途是非常有用的,所以为什么要从工具箱中扔掉一个工具呢?它是基于一些夸张的东西,比如警告,什么都不能解决——它消除了数组处理,简化了不需要返回值的并行承诺的链接,正如您应该知道的,在第不管怎样,所有的案件都在处理中。这个答案应该是否定的:Hi@Gon
生态编码。请不要在你的回答中添加投票评论?这适合于评论,但在其他方面,噪音会分散人们对其他好内容的注意力。谢谢。@halfer:我不再发帖了,但我对任何原创作品的无知感到恼火。现在我对自己保留所有的新想法:你的答案反应过激,你对问题标题的编辑也是如此。OP已经知道如何进行AJAX调用并获取延迟对象数组。问题的唯一一点是如何将该数组传递给$。when。我认为如果有可用的选项,用示例详细解释会更好。为此,我认为没有必要进行向下投票。向下投票是针对1的。甚至建议同步,尽管建议不要使用2。示例中的劣质代码包括。。。在阵列中?!1.同意,不应该推荐2.不同意-为了。。。在中是可以的,因为数组只包含那些不需要额外属性的属性。thanx anywaysre:2-问题是它可能会被其他无法保证的人复制,或者愚蠢到添加到Array.prototype。无论如何,对于非性能关键代码,最好使用.map而不是for/push循环,例如var promises=capitalCities.mapajaxRequest;$。when.apply$,promises.thenfillCountryCapitals-完成任务。代码中存在一个小问题,当数组中只有一个元素时,results数组只返回该结果,而不是一个包含单个元素的数组,这将破坏需要数组的代码。要修复此问题,请使用此函数var toArray=函数args{return deferreds.length>1?$.makeArrayargs:[args];}而不是Array.prototype.slice.call。
var arrayOfFn = [];
for (var i = 0; i < someDataArray.length; i++) {
    var ajaxFnForArray = new ajaxFn(someDataArray[i]);
    arrayOfFn.push(ajaxFnForArray);
}
$.when(
    $.each(arrayOfFn, function(index, value) {
        value.call()
    })
).then(function() {
        alert("Cheer!");
    }
)
$.when(...deferreds).done(() => {
    // do stuff
});
    // 1st
    function Outer() {
        var deferreds = GetAllData();

        $.when.apply($, deferreds).done(function () {
            // now you can do whatever you want with the updated page
        });
    }

    // 2nd
    function GetAllData() {
        var deferreds = [];
        $('.calculatedField').each(function (data) {
            deferreds.push(GetIndividualData($(this)));
        });
        return deferreds;
    }

    // 3rd
    function GetIndividualData(item) {
        var def = new $.Deferred();
        $.post('@Url.Action("GetData")', function (data) {
            item.html(data.valueFromAjax);
            def.resolve(data);
        });
        return def;
    }