0

my code works fine as long as every request returns successful. But if there ist just one single fail "always" doesn't fire.

I expect "always" always to fire. So far I had no luck finding an answer to my problem. "complete" (which I use for single requests) doesn't work. "then" neither.

var counter = { ok:0, fail:0 };

for(var i in toDoList)
{
  spRequest[i] = $.ajax({...})
  .done( function() { counter.ok   ++; } )
  .fail( function() { counter.fail ++; } );
}

$.when.apply(this, spRequest)
.always
(
  function()
  {
    if ( spResp.ok == paybackTable.length )
    {
      console.log( "everything went just fine" );
    }
    else
    {
      console.log( "there were some problems:" );
      console.log( "- Requests OK: " + counter.ok );
      console.log( "- Requests failed: " + counter.fail );
    }
  }
);

my "There were some problems" section is never reached

  • This might help: Handle well error in ajax, and your code will be able to do the $.when.apply line. http://stackoverflow.com/questions/2810128/try-catch-with-jquery-ajax-request Use window.onerror to see errors – Destrif Jun 10 '16 at 09:25

1 Answers1

0

IMHO there are some inaccuracies in your code. First of all, when you call $.when.apply(), between .when() parenthesis, you have to put "$" as first arguments, then your array spRequest. If you work with jQuery.Deferred you can control better the final result of your Deferreds (ajax calls and so on...). So, you push in spRequest array your Deferreds, that are executed ASAP. $.when.apply($,spRequest) waits for all Deferreds to be resolved or rejected. I deliberately put self.resolve() in every ajax.fail() instead of self.reject() because of two reasons:

  • you want to count your ajax fails;
  • if in a series of Deferred objects one of them fails, $.when.fail() fires and I think is not what you're searching for, or, better, I suppose that the files called by your ajax calls exist and can be correctly called. On the other hand, if it is not so, you have two possibilities:

    • use self.reject() on ajax.fail();
    • consider to check statusCode in your ajax call:

    $.ajax({ statusCode: { 404: function() { //resolve and counter ++ stuffs in here } } });

Here it is an example that goals your needs:

* index.php *

<html>
<head>
<title>TEST DEFERRED</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
</head>
<body>
<h1>TEST DEFERRED</h1>
<script src="js/test.js"></script>
</body>
</html>

* test.js *

var counter = { ok:0, fail:0 }
,toDoList = [1,2,3,4,5,6,7,8,9,10]
,spRequest = [];

for(var i in toDoList)
{
  console.log(i, i&1);
  if(i&1)
  {
    console.log('odd, request an ok ajax call');
    spRequest[i] = jQuery.Deferred(function(){
      console.log('function ok called!');
      var self = this;

      $.ajax({
        url: 'ajax/ajax_return_ok.php',
        async: true,
        data : {},
        type: 'post',
        dataType: 'json'
      }).done( function(d) {
        console.log(d);
        if(d.is_error)
        {
          counter.fail ++;
          self.resolve();
        } else {
          counter.ok   ++;
          self.resolve();
        }

      }).fail( function(j) {
        console.log(j.responseText);
        //# fail of ajax call
        counter.fail ++;
        self.resolve();
      });

    });
  } else {
    console.log('odd, request an error ajax call');
    spRequest[i] = jQuery.Deferred(function(){
      console.log('function error called!');
      var self = this;

      $.ajax({
        url: 'ajax/ajax_return_error.php',
        async: true,
        data : {},
        type: 'post',
        dataType: 'json'
      }).done( function(d) {
        console.log(d);
        if(d.is_error)
        {
          counter.fail ++;
          self.resolve();
        } else {
          counter.ok   ++;
          self.resolve();
        }

      }).fail( function(j) {
        console.log(j.responseText);
        //# fail of ajax call
        counter.fail ++;
        self.resolve();
      });

    });
  }

}


jQuery.when.apply($,spRequest).done(function(){
  console.log('when done');
}).fail(function(){
  console.log('when fail');
}).always(function(){
  if ( counter.fail === 0 )
  {
    console.log( "everything went just fine" );
  }
  else
  {
    console.log( "there were some problems:" );
    console.log( "- Requests OK: " + counter.ok );
    console.log( "- Requests failed: " + counter.fail );
  }
});

* ajax_return_error.php *

<?php
echo json_encode(array('is_error' => true,'error_message' => 'this is an error message'));

* ajax_return_ok.php *

<?php
echo json_encode(array('is_error' => false,'result' => 'ok'));

Apologize in advance for not having create a Fiddle.

Hope my answer helps.

Nineoclick
  • 804
  • 9
  • 17