2015-06-19 2 views
9

Мое приложение работает до 180 заданий AJAX, которые интенсивно работают на стороне сервера (длинные запросы SELECT).Параллельные запросы AJAX в jQuery

Я хотел бы оптимизировать нагрузку на несколько ядер процессора, которые у меня имеются, переключение с дизайна, в котором каждый вызов AJAX выполняется последовательно для дизайна, в котором эти запросы выполняются, максимум, скажем, 4 в параллельны друг другу.

Возможный, но некрасиво решение может быть выдачи всех запросов на 180, в то же время на клиенте, чтобы сервер использовать Semaphore хранят при Session или Application уровне. Ниже я расскажу о загрузке приложений.

Я хотел бы найти более приятное решение, в котором все вызовы начинаются по порядку (каждая строка на таблице представляет собой другой запрос проверки), но когда кто-то завершает работу, начинается следующий и появляется число (а именно 4) одновременных запросов AJAX с их соответствующими индикаторами загрузки.

Я пытался использовать Threadpool-js, но я нашел себя, что я не могу использовать JQuery из рабочих

Мой текущий код выглядит следующим образом

function GlobalCheck() { //entry point 
     if (ValidateDate()) { 
      //Below are global variables 
      list = $(".chkClass:checked"); //Only checked rows deal to AJAX request 
      num = $(".chkClass:checked").length; //Total number of ajax calls 
      done = 0; //Count of complete calls. When it reaches num we are done! 

      if (list.length == 0) { 
       alert('...'); 
       return; 
      } 

      $(".pMessage").fadeOut(); 
      $(".tbStatus").html(''); 
      $(".submit").hide(); 
      $(".exportFunctions").fadeOut(); 
      $(".loader").show(); 
      $(":checkbox").attr('disabled', true); 

      SingleCheck(0); //simplification, I do other non interesting things here 
     } 
    } 


function SingleCheck(index) { 
     aValue = $($(list).get(index)).val(); 

     var splitted = aValue.split('_'); 
     $('#loader_' + aValue).show(); 
     $('#green_' + aValue).hide(); 
     $('#yellow_' + aValue).hide(); 
     $('#red_' + aValue).hide(); 
     $('#print_' + aValue).hide(); 
     $('#xls_' + aValue).hide(); 
     $('#summ_' + aValue).hide(); 

     $.ajax({ 
      type: 'GET', 
      url: '@Url.Action("Single", "Check")', 
      data: { 
       pType: splitted[0], 
       pIdQuery: splitted[1], 
       pDateBegin: $('#date_begin').attr('value'), 
       pDateEnd: $('#date_end').attr('value'), 
       pNow: Math.floor(Math.random() * 1000000) 
      }, 
      success: function (data) { 
       if (!CheckSessionExpired(data)) { 
        //alert(data); 

        $("#tdStatus_" + aValue).html(data); 
        $("#loader_" + aValue).hide(); 
        done++; //Done 1 more query 
        $(".progress").each(function (i, cRow) { $(this).html([update status]); }); 

        if (done == num) { // Finish? 
         FinishCheck(); 
        } 
        else { 
         SingleCheck(done); //Go to the next 
        } 
       } 
      }, 
      error: function (XMLHttpRequest, textStatus, errorThrown) { 
       alert(errorThrown); 
       RedirectToError(); 
      } 
     }); 
    } 

Результат заключается в следующем:

Auitool

Вопрос: какой подход можно использовать для создания параллельных запросов AJAX в моем сценарии?

[изменить] забыл обсудить требования приложений: это приложение работает вживую, но не обслуживает большую пользовательскую базу. Когда пользователь отправляет данные для проверки, приложение будет выполнять интенсивную работу, оставаясь бездействующим в течение длительного периода времени.

ответ

2

$.ajax() - это асинхронная функция, которая инициирует запрос, а затем немедленно возвращается. Поэтому, если вы вызываете его несколько раз подряд, он будет создавать параллельные запросы.

Ваш код по-прежнему работает в одном потоке, но HTTP-запросы выполняются параллельно в фоновом режиме, а jQuery вызывает ваши обратные вызовы при их возврате. Таким образом, вы получаете параллельность без непосредственного взаимодействия с потоками.

В вашем GlobalCheck():

var CONCURRENT_REQUESTS = 4; 

while (done < CONCURRENT_REQUESTS) { 
    SingleCheck(done++); 
} 

начнет четыре параллельных запросов, и существующий код будет инициировать новый запрос каждый раз, когда один заканчивается, так что вы всегда будете иметь 4 параллельных запросов работает. И потому, что код работает только на одном потоке, вам не придется беспокоиться о проблемах параллелизма с вашей done переменных и т.д.

Для более одновременных запросов, просто увеличить значение CONCURRENT_REQUESTS, но учтите, что очень быстро вы попадете на ограничение одновременных запросов браузера на один домен - он зависит от каждого браузера, но это всегда довольно небольшое число. See this answer for specifics.

1

Когда вы, например, имеете вызов ajax в функции «doCall», просто запустите эту функцию для x-суммы, зависящей от «потоков», которые вы хотите.

Сейчас у вас есть 3 темы. Чтобы сохранить это, перезапустите функцию в функции. Итак, в doCall Function у вас есть еще один doCall (x), чтобы «сохранить поток в живых».

У вас будет какая-то «петля», и запросы будут продолжать асинхронную работу.

0

На мой взгляд, вам нужен массив «nbRequest», чтобы узнать, сколько запросов у вас есть. (4 макс.)

Тогда используйте setInterval.

Запустите интервал, сохраните «num» внутри «nbRequest». Когда запрос ajax завершен, удалите «num» из «nbRequest».

Между прочим, интервал «проверяет, равна ли длина« nbRequest »4. Если нет, вы начинаете новый запрос.

Когда «done == num», остановите интервал.

0

Примечание: количество одновременных запросов, которые могут выполнять браузеры к данному домену, ограничено. Таким образом, вы можете одновременно запустить все ваши запросы, браузер будет заботиться о их очередности и одновременно выполнять от 6 до 8 одновременно.

Источник: Max parallel http connections in a browser?

Однако, если вы хотите получить более точный контроль, вы могли бы реализовать что-то вроде этого:

//define your list of URLs and what to do with the data 
var sources = [ 
    { 
     url : "http://...", 
     callback : function(data){ /* do something */} 
    }, 
    { 
     url : "http://...", 
     callback : function(data){ /* do something */} 
    } 
]; 

//state 
var maxConcurrentRequests = 4; 
var concurrentRequests = 0; 
var currentSourceIndex = -1; 

//this function wil ensure that as long as there are sources left, there are 4 requests running 
function startRequestIfNeeded(){ 

    while(currentSourceIndex < sources.length-1 && concurrentRequests < maxConcurrentRequests){ 
     currentSourceIndex++; 
     concurrentRequests++; 
     var source = sources[sourceIndex]; 
     doRequest(source); 
    } 
} 

//this fires the request and executes the callback 
function doRequest(source){ 

    $.getJSON(source.url, function(data){ 
     source.callback(data); 
     concurrentRequests--; 
     startRequestIfNeeded(); 
    }); 
} 

startRequestIfNeeded(); 

Я оставлю обработку ошибок для вас.

И если вам нужно будет добавить логику, если вы хотите обнаружить, когда все запросы выполнены. Возможно, посмотрите на обещания.

+0

Спасибо, я обновил свой ответ и связался с более актуальным вопросом. –

Смежные вопросы