jquery foreach循环中的javascript函数不等待响应

时间:2015-02-18 07:32:48

标签: javascript jquery asynchronous foreach

我的foreach循环:

jQuery(".custom-checkbox").each(function() {
      if (jQuery(this).attr('data-action') == 'true') {

      if(deleteQuoteItemFromListing(jQuery(this).attr('data-id'))){
                    console.log('passed');
            }else{
                    console.log('failed');
            }
      }    
 });

功能是(它使用原型)但它成功了

function deleteQuoteItemFromListing(id){
    //does someoperations and on success
    delurl = getDelUrl()+id; //baseurl/module/action/delete/id
    new Ajax.Request(delurl,{
        method: 'get',
        onSuccess: function(transport){
            return TRUE;
        } 
    })
}

但问题是所有foreach一次执行,并且不等待函数的响应。即使操作成功,也会打印failed

更新

我首先尝试的另一种方式是

jQuery('.delete-from-quote').click(function() {
        var i = 0, j = 0;
        jQuery(".custom-checkbox").each(function() {
            if (jQuery(this).attr('data-action') == 'true') {
                i++;
            }
        });


        if (i == 0) {
            alert('please choose product');
            return false;
        }

        jQuery(".custom-checkbox").each(function() {

            if (jQuery(this).attr('data-action') == 'true') {

                var urlData = "<?php echo $this->getUrl('qquoteadv/index/delete/'); ?>";
                urlData += "id/" + jQuery(this).attr('data-id') + "/"

                var ajax = jQuery.ajax({
                    type: "GET",
                    url: urlData,
                    success: function(msg) {
                        j++;
                    }
                })

            }
          if(i==j){location.reload();} //after completing all, reload the page
        });
  });

问题是知道所有操作已完成并重新加载页面。

4 个答案:

答案 0 :(得分:3)

我的猜测是你省略的代码是进行异步ajax调用。由于默认情况下ajax是异步的,因此您在那里编写的代码($.ajax或其他)启动进程,但随后代码继续运行时,该进程将在后台继续。

没有合理的方法让deleteQuoteItemFromListing函数等待以获得响应。 (虽然它可以执行同步 ajax,A)但它通过锁定浏览器UI会导致糟糕的用户体验,并且B)jQuery将在某个阶段删除该选项,强制执行如果你想继续这样做,你可以直接去XHR。)

相反,通过让您的函数返回promise或接受回调,然后解析promise或在完成后调用回调来重构您的代码以包含Web编程的异步性质。

这里概述了承诺版本的样子:

jQuery(".custom-checkbox").each(function() {
    if (jQuery(this).attr('data-action') == 'true') {
        deleteQuoteItemFromListing(jQuery(this).attr('data-id'))
            .done(function(id) {
                console.log(id + ' passed');
            })
            .fail(function(id) {
                console.log(id + ' failed');
            });
    }    
});

function deleteQuoteItemFromListing(id){
    var d = jQuery.Deferred();
    jQuery.ajax(/*...*/)
        .done(function() {      // This bit assumes the deletion worked if
            d.resolveWith(id);  // the ajax call worked, and failed if the
        })                      // ajax call failed; if instead the ajax
        .fail(function() {      // call always works and returns a flag,
            d.rejectWith(id);   // adjust accordingly
        });
    return d.promise();
}

答案 1 :(得分:2)

使用回调可确保执行该功能。

jQuery(".custom-checkbox").each(function () {
    if (jQuery(this).attr('data-action') == 'true') {
        deleteQuoteItemFromListing(jQuery(this).attr('data-id'), handleData);

    }
});

    function handleData(data) {
    if (data) {
        console.log('passed');
    } else {
        console.log('failed');
    }
}


function deleteQuoteItemFromListing(id, callback) {
    //does someoperations and on success
    delurl = getDelUrl() + id; //baseurl/module/action/delete/id
    new Ajax.Request(delurl, {
        method: 'get',
        onSuccess: function (transport) {
            callback(true);
        }
    })
}

我希望这对你有用。你需要在另一个函数之外定义handleData函数。

答案 2 :(得分:1)

(部分)您的问题出在这个简单的陈述中:

return TRUE;

在JavaScript中,“true”布尔值以小写形式写出:

return true;

解释器认为TRUE是一个变量,并且会抛出一个ReferenceError,因为它没有在任何地方设置/定义,这意味着该函数永远不会返回true

答案 3 :(得分:1)

使用jquery时。

您需要将Deferred数组中的Deferred排队,然后立即应用所有函数。

如果一个人失败,所有人都会失败,如果一切都成功,所有人都会失败。

查看jQuery When

      var queue = [];
      var items = 0;
      return new $.Deferred(function (deferred) {
      $(".custom-checkbox").each(function () {
       if ($(this).attr('data-action') == 'true') {
        items++;
        queue.push(function () {
            new Ajax.Request(delurl, {
                method: 'get',
                onSuccess: function (transport) {
                    items--;
                    if(items === 0)
                        deferred.resolve();
                },
                onError:function(e){
                  deferred.reject(e);   
                }
            });
        });
    }
});

//now resolve all of the deferred fns

  $.when(queue).done(function(){
      console.log('All went well');
  })
 .fail(function(e){
      console.log('Error ' + e);
  });
});