views:

57

answers:

1

Hello, I'm making a mailing list script that takes advantage of ajax (async=false) to send emails in chunks.

Basically the cycle is this:

var i = 0;
for(i;i<num_rows;i=i+mxt){
    if($("#panic").val()=='1'){
        break;
    }
    perc = (i*100)/num_rows;
    startThread(i,perc);
}

Tha panic value is set by a button, the problem is that during the cycle (that works) I can't interact with the page.

What am I doing wrong?

Thank you

EDIT:

function startThread(i,perc){
l_a = i;
l_b = mxt;

headers = '&mail_from='+mail_from+'&mail_from_name='+mail_from_name+'&mail_subject='+mail_subject;

$.ajax({  
    type: "POST", url: "ajax/thread.php", data: "l_a="+l_a+"&l_b="+l_b+headers, 
    success: function(html){ $("#progressbar").progressbar({value: perc}); },
    async: false
 });
}
+3  A: 

Your startThread() function name is misleading, because JavaScript in web browsers in not only single threaded, but it shares the same thread with the page rendering.

Since you're using async=false, the $.ajax call become a blocking function, and this blocks the page rendering thread, making the UI unresponsive.

Quoting the jQuery documentation (emphasis added):

async

Default: true

By default, all requests are sent asynchronous (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

Possible solutions:

  • Piggyback your data in one JSON object, and send just one $.ajax request. If possible use async=true.
Daniel Vassallo
No, you are wrong, try to comment out the startThread from the for cycle and you'll see that it's the for cycle not the ajax calls that blocks the UI!
0plus1
I want to add something else. If you launch a for cycle with ajax calls (async) you are basically destroying the purpose of this. Each thread send chunks of email then pauses, If I launched 100+ concurrent ajax calls would be the same as sending them all to the smtp server.
0plus1
@0plus1: Thanks for the downvote :) ... However, both are blocking. The `$.ajax()` with `async=false` blocks until the server returns a response. That's typically a few tens/hundreds of milliseconds... The `for` loop blocks depending on the number of iterations. Doing a `while (true) { }` blocks the UI... I'm not aware of the logic of your application. Mine was just an attempt to show you why you were having problems.
Daniel Vassallo
@0plus1: Updated my answer with a citation from the jQuery docs.
Daniel Vassallo
@0plus1: He's really not wrong, the downvote is misplaced...
annakata
@Daniel so basically I'm screwed. I really need to have the synchronous request because they must run sequentially and return a result before moving to the next "thread". I wasn't aware that they completely lock down the browser.
0plus1
@0plus1: Is this solution for a public website, or is it going to be deployed in an internal/local environment? Because you could consider [Web Workers](http://en.wikipedia.org/wiki/Web_Workers) to have multiple threads in JavaScript. Web Workers can do Ajax requests. The only problem is that they are not supported in some popular browsers (IE). That's why I asked if this is a public thing... If you can use Web Workers, you may want to check this related article: http://hacks.mozilla.org/2009/07/working-smarter-not-harder/
Daniel Vassallo
@all I haven't downvoted Daniel just so you know. (http://imgur.com/hq8CI.jpg)
0plus1
@Daniel the solution will only be internal, thank you very much for the hint!
0plus1