【问题标题】:Chaining Ajax requests based results of jQuery .each only fires beforeSend once链接基于 Ajax 请求的 jQuery .each 请求结果只触发一次 beforeSend
【发布时间】:2013-07-04 14:24:59
【问题描述】:

我修改了 Magento 处理类别的方式,允许用户通过将添加到购物车 url 的 ajax 请求链接在一起,从类别页面一次添加多个可配置产品。

基本上,用户选择他们想要添加的项目的复选框,这使<li> 产品属于“活动”类。这个 jQuery 抓取每个具有活动类的 <li>,然后从变量 theLink 中的选定下拉菜单中抓取“添加到购物车 URL”。

$j('li.active').each(function(){
            var theLink = $j(this).find('.shopthislookpageselect').val();
            var successString = "was added to your shopping cart."
            $j.ajax({
                beforeSend: function(){$j('#modalBackground').show();},
                type:"POST",
                url: theLink,
                success: function(data){
                    var returnPage = data;
                    var exists = (returnPage.indexOf(successString) !== -1);
                    if (exists) {$j('.col-main').prepend('<ul class="messages"><li class="success-msg"><ul><li><span>The items selected were added to your shopping cart. View your cart <a href="https://www.culturekings.com.au/checkout/cart/">HERE</a></span></li></ul></li></ul>'); $j("html, body").animate({ scrollTop: 0 }, "slow"); }
                    else {alert ('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.')}
                    },
                error: function(){alert('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.');},
                complete: function(){$j('#modalBackground').fadeOut(200);}
            });
});

div modalBackground 是一个透明的全宽和全高覆盖,有一个加载 gif,应该在每个 ajax 调用开始时显示,并在结束时隐藏。

问题是 modalBackground 在第一个 ajax 调用开始时显示并在结束时隐藏,但之后的任何其他调用都不会再次显示。我可以看到这个函数仍在运行,因为我可以计算每次成功调用成功函数结束时显示的成功消息。

beforeSend 只触发一次吗?如果是,为什么?或者我应该对叠加层进行不同的处理。

请注意,如果不更改 Magneto 的添加到购物车控制器中的大事,它就无法一次处理添加所有产品,因此我被困在执行这些多个 Ajax 请求。

【问题讨论】:

    标签: javascript ajax jquery


    【解决方案1】:

    这是一种方法:

    // this will store the ajax requests with are jQuery.Deferred()
    var promises = [];
    
    // ajaxSettings.beforeSend is actually better to use to modify the xhr.
    // You can just do this beforehand.
    $j('#modalBackground').show();
    $j('li.active').each(function(){
       // all your other stuff
       // success and error callbacks will still run for each one.
       promises.push($j.ajax({
           type:"POST",
           url: theLink,
           success: function(data){
               var returnPage = data;
               var exists = (returnPage.indexOf(successString) !== -1);
               if (exists) {$j('.col-main').prepend('<ul class="messages"><li class="success-msg"><ul><li><span>The items selected were added to your shopping cart. View your cart <a href="https://www.culturekings.com.au/checkout/cart/">HERE</a></span></li></ul></li></ul>'); $j("html, body").animate({ scrollTop: 0 }, "slow"); }
               else {alert ('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.')}
           },
           error: function(){alert('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.');}
        }));
    });
    
    // What this does is gathers all those jQuery.Deferred and when
    // all of them are done, runs the done callback.
    $j.when.apply($, promises).done(function() {
        $j('#modalBackground').fadeOut(200);
    });
    

    这一切都发生在同一个函数中,所以不管你怎么称呼它,都一起做。

    要了解有关 Deferred() 的更多信息:http://api.jquery.com/category/deferred-object/

    【讨论】:

    • 这很棒而且效果很好。显然,我必须添加 var theLink = ... 和 var successString =... 位在 // 你所有其他东西都被评论的地方,它直接起作用了!干得好!
    【解决方案2】:

    在我看来,您正在处理与此操作的异步性质相关的时间问题。我建议解雇你的 $j('#modalBackground').show();命令一次并且只淡化一次。所以本质上你会想要做更多类似的事情:

    $j('li.active').each(function(index){
                if(index===0) {
                    $j('#modalBackground').show();
                }
                var theLink = $j(this).find('.shopthislookpageselect').val();
                var successString = "was added to your shopping cart."
                $j.ajax({
                    type:"POST",
                    url: theLink,
                    success: function(data){
                        var returnPage = data;
                        var exists = (returnPage.indexOf(successString) !== -1);
                        if (exists) {$j('.col-main').prepend('<ul class="messages"><li class="success-msg"><ul><li><span>The items selected were added to your shopping cart. View your cart <a href="https://www.culturekings.com.au/checkout/cart/">HERE</a></span></li></ul></li></ul>'); $j("html, body").animate({ scrollTop: 0 }, "slow"); }
                        else {alert ('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.')}
                        },
                    error: function(){alert('There was a problem adding these products to your cart. \n Please select the View Full Product Info link to add these items individually.');},
                    complete: function(){
                        if(index===($j('li.active').length-1)) {
                            $j('#modalBackground').fadeOut(200);
                        }
                    }
                });
    });
    

    此代码将防止不必要的显示和隐藏相互冲突,我想这是当前的问题。

    请记住,beforeSend 将在完成事件后立即触发,而完成事件的触发时间取决于响应的延迟时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      • 2018-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-23
      相关资源
      最近更新 更多