0

I was trying to make a brute force poll voting script.

$('#vote').click(function(e) {                                      
    var noOfvotes = 0;
    var noOfattempt =0;
    var noOffail =0;

    for(var i =0 ; i<500;i++){
        $.ajax({
            url: 'http://www.example.com/survey/',
            type: 'POST',                   
            data: {poll: '123',
                   vote:"option3"                             
                  },
        })
            .done(function() {
                noOfvotes++;
            })
            .fail(function() {
                noOffail++;
            })
            .always(function() {
                noOfattempt++;
            });
    }
    //Result printing
    console.log('No of attempt :' + noOfattempt);       
    console.log('No of done :' + noOfvotes);
    console.log('No of fail :' + noOffail); 
});

The issue i faced is result printing is executed before these ajax requests completed.So out put was like this on console

No of attempt :0   
No of done :0
No of fail :0

But I need to get these lines executed after all Ajax requests finishes. How can I make a blocking code for this situation.

Mo.
  • 26,306
  • 36
  • 159
  • 225
Sanoob
  • 2,466
  • 4
  • 30
  • 38
  • read about callbacks http://stackoverflow.com/questions/9596276/how-to-explain-callbacks-in-plain-english-how-are-they-different-from-calling-o – rafaelcastrocouto Mar 06 '14 at 18:20
  • I think you're missing the entire point of having callbacks. They exist because you *don't* want requests to block. Instead of using blocking code, you need to change your approach so that whatever needs the response will be called inside a callback. – cookie monster Mar 06 '14 at 18:20
  • put the print in the success call back of the ajax function (.done) – Huangism Mar 06 '14 at 18:21
  • 2
    Well making 500 silmutanous requests can only bring you issues... – A. Wolff Mar 06 '14 at 18:22
  • 1
    ...and sending out 500 XHR requests at once isn't a great idea. Why are you trying to cheat a poll in the first place? – cookie monster Mar 06 '14 at 18:22
  • @A.Wolff This is not about DoS attack, I just need to know how to make a call back function when there is a loop. adeneo freekish helped with the stack idea. – Sanoob Mar 06 '14 at 18:27
  • @Shanoop ya, i see now what you are looking for – A. Wolff Mar 06 '14 at 18:29
  • @A.Wolff If I were asking this question without example I would have got -10. I faced a coding situation that is the point you wanna look. – Sanoob Mar 06 '14 at 18:31

3 Answers3

4

Stack the requests in an array and use $.when to determine when they are all done

$('#vote').click(function (e) {
    var XHR         = [],
        noOfvotes   = 0,
        noOfattempt = 0,
        noOffail    = 0;

    for (var i = 0; i < 500; i++) {
        XHR.push(
            $.ajax({
                url: 'http://www.example.com/polling/',
                type: 'POST',
                data: {
                    poll: '123',
                    vote: "option3"
                },
            }).done(function () {
                noOfvotes++;
            }).fail(function () {
                noOffail++;
            }).always(function () {
                noOfattempt++;
            })
        );
    }

    $.when.apply(undefined, XHR).done(function() {
        console.log('No of attempt :' + noOfattempt);
        console.log('No of vote :' + noOfvotes);
        console.log('No of fail :' + noOffail);
    });
});
adeneo
  • 312,895
  • 29
  • 395
  • 388
3
$('#vote').click(function(e) {                                      
    // some code

    var requests = [];
    for(var i = 0; i < 500; i++){
        requests.push($.ajax({ ... }));
    }
    $.when.apply($, requests).then(function() {
        console.log('No of attempt :' + noOfattempt);       
        console.log('No of vote :' + noOfvotes);
        console.log('No of fail :' + noOffail); 
    });
});

EDIT Note that .when fires when all requests finish the job or one of them fails. If you want to fire a callback after all of requests finish (no matter whether there's an error or not), then try this:

var custom_when = function(reqs) {
    var def = $.Deferred(),
        counter = reqs.length;
    for (var i = 0; i < counter; i++) {
        reqs[i].always(function() {
            counter--;
            if (!counter) {
                def.resolve();
            }
        });
    }
    return def.promise();
};

and use it like that:

custom_when(requests).then(...);
freakish
  • 54,167
  • 9
  • 132
  • 169
1

Move the log statements into .always and check that the noOfattempt is equal to the amount you tried.

.always(function() {
  noOfattempts++;
  if (noOfattempts === 500) {
    // we're done
  }
 })
Matt Pileggi
  • 7,126
  • 4
  • 16
  • 18