¿Alguna mejor manera de combinar múltiples devoluciones de llamada?

Necesito llamar a una función asíncrona (con bucle) para varios valores y esperar esos resultados. Ahora mismo estoy usando el siguiente código:

(function(){
    var when_done = function(r){ alert("Completed. Sum of lengths is: [" + r + "]"); }; // call when ready

    var datain = ['google','facebook','youtube','twitter']; // the data to be parsed
    var response = {pending:0, fordone:false, data:0}; // control object, "data" holds summed response lengths
        response.cb = function(){ 
            // if there are pending requests, or the loop isn't ready yet do nothing
            if(response.pending||!response.fordone) return; 
            // otherwise alert.
            return when_done.call(null,response.data); 
        }

    for(var i=0; i<datain; i++)(function(i){
        response.pending++; // increment pending requests count
        $.ajax({url:'http://www.'+datain[i]+'.com', complete:function(r){
            response.data+= (r.responseText.length);
            response.pending--; // decrement pending requests count
            response.cb(); // call the callback
        }});
    }(i));

    response.fordone = true; // mark the loop as done
    response.cb(); // call the callback
}()); 

Esto no es todo muy elegante pero hace el trabajo. ¿Hay alguna forma mejor de hacerlo? Quizás una envoltura?

Respuestas a la pregunta(2)

Su respuesta a la pregunta