在 each() 函数内进行多次 ajax 调用。然后在所有调用都完成后做些什么?

IT技术 javascript jquery ajax each
2021-01-17 03:16:17

让我稍微解释一下我的代码(如果有问题请见谅,我刚刚从头开始编写了这个示例,它与我目前拥有的非常接近)。

HTML:

<form id="form">
    <!-- Friend 1 -->
    Name 1: <input type="text" name="friendName1" id="friendName1" class="friendName" value=""><br />
    Email 1: <input type="text" name="friendEmail1" id="friendEmail1" value=""><br /><br />
    <!-- Friend 2 -->
    Name 2:<input type="text" name="friendName2" id="friendName2" class="friendName" value=""><br />
    Email 2:<input type="text" name="friendEmail2" id="friendEmail2" value=""><br /><br />
    <!-- Friend 3 -->
    Name 3:<input type="text" name="friendName3" id="friendName3" class="friendName" value=""><br />
    Email 3:<input type="text" name="friendEmail3" id="friendEmail3" value=""><br /><br />
    <!-- Friend 4 -->
    Name 4:<input type="text" name="friendName4" id="friendName4" class="friendName" value=""><br />
    Email 4:<input type="text" name="friendEmail4" id="friendEmail4" value=""><br /><br />
    <!-- Submit -->
    <input name="submit" type="submit" value="Submit">
</form>

JS:

$("#form").submit(function(){

    $(".friendName[value!='']").each(function(){
        var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
        if($("#"+idEmail+"[value!='']").length > 0){
            var name = $(this).val();
            var email = $("#"+idEmail).val();

            // Submit the ajax request
            $.ajax({ 
                type: 'POST', 
                url: 'ajax/url', 
                data: {
                    name: name,
                    email: email
                },
                success: function(json) {
                    // Log a console entry if our ajax request was successful
                    console.log(name + " was submitted via ajax");
                }
            });
        }
    });

    // Redirect the user to the thank you page
    setTimeout( function() { window.location= '/thanks'; }, 2000 );

});

JSFiddle(重定向删除和ajax调用替换为小提琴的控制台日志)

http://jsfiddle.net/cM5PX/

HTML 是一个简单的表单,带有朋友姓名和朋友电子邮件输入字段。

JS 有一个 each 函数,如果名称和关联的电子邮件有值,它会运行一个 ajax 调用。

我需要一种方法来运行这些 ajax 调用(可能有 1 个循环,可能有 15 个),然后在它们全部完成后,重定向到新页面。

我目前的做法很糟糕,因为所有的 ajax 调用在页面重定向之前都没有完成运行。

我能做些什么来改善这种情况?它需要万无一失,并且仅在所有 ajax 调用完成后才重定向(成功或错误,无关紧要 - 只需要在完成后重定向)。

我试过使用,async: false但它似乎没有什么区别。

我想过在 each 函数中放置一个计数器,在 ajax 成功函数中放置一个计数器,如果它们都匹配,则进行重定向,但我正在寻找一些更有经验的指导。

4个回答

使用延迟对象

$("#form").submit(function(e){

    e.preventDefault();

    var calls = [];

    $(".friendName[value!='']").each(function(){
        // Submit the ajax request
        calls.push($.ajax({ 
            type: 'POST', 
            url: 'ajax/url', 
            data: {
                name: name,
                email: email
             },
             success: function(json) {
                // Log a console entry if our ajax request was successful
                console.log(name + " was submitted via ajax");
             }
         }));
    });

    $.when.apply($, calls).then(function() {
        window.location= '/thanks';
    });
});
这太棒了,难怪你有 157k!;) 很好的答案!
2021-03-30 03:16:17
这听起来很聪明,我会试一试,让你知道我是怎么做的。
2021-03-31 03:16:17

好的,这很容易,因为您使用的是 jQuery。jQuery 带有一个集成的promise maker,它也与jQuery 的Ajax 调用相连。这意味着什么?好吧,我们可以很容易地这样做:

var requests = [ ];

// ...

// Submit the ajax request
requests.push($.ajax({ 
    type: 'POST', 
    url: 'ajax/url', 
    data: {
        name: name,
        email: email
    },
    success: function(json) {
        // Log a console entry if our ajax request was successful
        console.log(name + " was submitted via ajax");
    }
}));

// at this point we filled our array with jXHR objects which also inherit the promise API

$.when.apply( null, requests ).done(function() {
    document.location.href = '/thanks';
});

注意:只有在所有请求都成功完成后,上面的代码才会触发。如果您需要处理一个.then()多个请求失败的情况,也可以使用.fail()代替.done()

菲利克斯打败了你!:(虽然+1。
2021-03-28 03:16:17
确实,我做了太多的“blabla”:p
2021-04-04 03:16:17
确实,这里没有第二名:p
2021-04-14 03:16:17

只需保留 AJAX 调用的计数器并检查它们何时全部完成。像这样的东西:

$("#form").submit(function(){
    var ajaxMax = $(".friendName[value!='']").length, ajaxCounter = 0;
    $(".friendName[value!='']").each(function(){
        var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
        if($("#"+idEmail+"[value!='']").length > 0){
            var name = $(this).val();
            var email = $("#"+idEmail).val();

            // Submit the ajax request
            $.ajax({ 
                type: 'POST', 
                url: 'ajax/url', 
                data: {
                    name: name,
                    email: email
                },
                success: function(json) {
                    // Log a console entry if our ajax request was successful
                    console.log(name + " was submitted via ajax");
                    if(++ajaxCounter >= ajaxMax)
                        window.location= '/thanks';
                }
            });
        }
    });
});
我刚刚意识到我发布的代码无法正常工作,因为您有一个“if”语句,因此在计算“max”时需要检查它。
2021-04-03 03:16:17

默认情况下 $.ajax 是异步的。在传递的选项哈希中,添加

async: false

这将序列化您正在进行的调用,使其按照您想要的方式执行。


从原始海报获得评论后,可能的解决方案可能是执行以下操作:

  • 在提交调用中确定应该进行的调用次数。
  • 将此结果存储为处理程序函数中的局部变量
  • 在“完成:”上创建一个回调,将检查调用的值
    • 如果要进行的调用次数大于 0,则递减该值并返回
    • 如果调用次数达到零,则更新 window.location(确实应该使用 window.location.href,因为 window.location 是一个对象,但浏览器将允许这样做并正确执行)

请注意,我没有任何关于执行此类操作的线程安全性的信息,所以 YMMV。


示例代码:

$("#form").submit(function(eventObject){
    var $ajaxFields= $(".friendName[value!='']").filter(function(index){
        var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
        return ($("#"+idEmail+"[value!='']").length > 0);
    });

    var numberToSubmit= $ajaxFields.length;
    $ajaxFields.each(function(){
        var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
        var name = $(this).val();
        var email = $("#"+idEmail).val();

        // Submit the ajax request
        $.ajax({ 
            type: 'POST', 
            url: 'ajax/url', 
            data: {
                name: name,
                email: email
            },
            success: function(json) {
                // Log a console entry if our ajax request was successful
                console.log(name + " was submitted via ajax");
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log("call not completed: "+textStatus);
            },
            complete: function(jqXHR, textStatus) {
                if( --numberToSubmit == 0 ) {
                    window.location.href= '/thanks';
                }
            }
        });
    });

    // Prevent default form submission
    return false;
});
下面使用延迟对象的评论可能是更聪明的方法,不幸的是我没有任何使用它们的经验。
2021-04-02 03:16:17
啊好吧......让我稍微挖掘一下。
2021-04-04 03:16:17
刚刚更新了我的问题,我试过使用 async: false 但它似乎没有什么区别,我真的不希望浏览器在调用时冻结。
2021-04-10 03:16:17