2013-06-21 2 views
8

Ситуация:
Я использую $ .ajax() POST для отправки запроса на php-скрипт, который вставляет около 400 000-500 000 строк в db. Это примерно 3,5 - 4 минуты. (В течение этого времени запрос ОТПРАВЛЯЕТСЯ).

Проблема:
мне нужен какой-то способ, чтобы показать прогресс на этой странице. (например,%). Я попытался использовать $ .ajax() в setInterval, который проверяется каждые 5 секунд или около того, но они, похоже, накапливаются, и все заканчиваются, когда завершается первый (более длинный) $ .ajax().

Вопрос:
Не $ .ajax() асинхронной по умолчанию? Разве это не означает, что запросы могут быть отправлены в любом порядке и в любое время, и ответы должны быть получены в любом порядке и в любое время? Это даже имеет отношение к async? Есть ли способ периодически отправлять «полу-ответы» с одного запроса? Или я не могу отправлять и получать запросы/ответы во время ожидающего запроса/ответа? (см. примерный рисунок ниже)

Заранее спасибо!

multiple requests http://kshaneb.com/reqres.png

+2

+1 для графа. :) Считаете ли вы, что вы разбиваете свои данные, т. Е. Отправляете отдельные запросы по 10k строк? –

+1

+1 для объяснения. сделал u попытался с async true .. – sathish

+0

Я согласен с Zsolt выше, рассмотрите разбиение ваших данных на несколько меньших запросов, которые могут дать вам более быстрый ответ, также вы можете рассчитать% основы от количества выполненных запросов. Кроме того, загрузка больших данных в один запрос, хотя и асинхронная, также приведет к более низкой производительности. –

ответ

1

Вместо того, чтобы делать в Ajax пост вы можете оставить на IFRAME и есть PHP генерировать Приростная и отправить его с помощью команды flush.

// send a hash mark for every 1000 inserts 
$a = 0; 
while ($rec = getDataForNextInsert()){ 
     $a++; 
     // do insert 
     if ($a%1000 == 0) { echo '#'; flush(); } 
} 

Также можно было бы опросить содержимое iframe, чтобы обеспечить прекрасный дисплей для конечного пользователя.

2

Надеется, что это помогает

$(function() 
    { 
     var statusElement = $("#status"); 

     // this function will run each 1000 ms until stopped with clearInterval() 
     var i = setInterval(function() 
     { 
      $.ajax(
      { 
       success: function (json) 
       { 
        // progress from 1-100 
        statusElement.text(json.progress + "%"); 

        // when the worker process is done (reached 100%), stop execution 
        if (json.progress == 100) clearInterval(i); 
       }, 

       error: function() 
       { 
        // on error, stop execution 
        clearInterval(i); 
       } 
      }); 
     }, 1000); 
    }); 
+0

Ваш вызов AJAX не содержит URL. Возможно, так и должно быть. –

7

Ваш давний Ajax-вызову, вероятно, открывает сеанс на сервере, поэтому все последующие запросы блокируются из-за блокировки файла сеанса.

Проблема: PHP записывает свои данные сессии в файл по умолчанию. Когда выполняется запрос на скрипт PHP, который запускает сеанс (session_start()), этот файл сеанса заблокирован. Это означает, что если ваша веб-страница делает многочисленные запросы на PHP-скрипты, например, для загрузки содержимого через Ajax, каждый запрос может блокировать сеанс и предотвращать выполнение других запросов. Другие запросы будут зависать на session_start(), пока файл сеанса не будет разблокирован. Это особенно плохо, если один из ваших запросов Ajax относительно длительный.

Файл сеанса связи остается заблокированным до тех пор, пока скрипт не завершится или сеанс будет закрыт вручную. Чтобы предотвратить блокирование нескольких запросов PHP (которые требуют данных $ _SESSION), вы можете начать сеанс, а затем закрыть сеанс. Это разблокирует файл сеанса и позволит оставшимся запросам продолжить работу, даже до завершения первоначального запроса.

Больше информации здесь: http://konrness.com/php5/how-to-prevent-blocking-php-requests/

+2

[Было бы желательно] (http://meta.stackexchange.com/q/8259) включить сюда важные части ответа (не только причину, но и решение) и предоставить ссылку для справки. –

+0

Спасибо @optimistiks. Как было предложено в этой статье, я использую session_write_close(), прежде чем запускаю много времени на мой скрипт php и ... Он работает! Ну на localhost в любом случае. Я уверен, что, когда я нажимаю все это на сервер, появятся новые проблемы. Еще раз спасибо! – ksb86

1

Я надеюсь, что это будет полезно для вас

Прежде всего, вам необходимо отключить буфер вывода в вашем PHP скрипт

@apache_setenv('no-gzip', 1); 
@ini_set('zlib.output_compression', 0); 
@ini_set('implicit_flush', 1); 
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); } 
ob_implicit_flush(1); 

Тогда вам нужно повторить свой прогресс с PHP во время процесса, что-то вроде этого:

for($i=0;$i < 20;$i++){ 
    echo ($i > 0 ? "#":"").($i/20*100); 
    sleep(1); 
} 

Затем в javascript необходимо прослушать событие изменения xhr readystate, и когда это произойдет, просто проанализируйте текст ответа и покажите прогресс, какой вы хотите.

прослушивания для события:

$.ajaxPrefilter(function(options, _, jqXHR) { 
       if (options.onreadystatechange) { 
        var xhrFactory = options.xhr; 
        options.xhr = function() { 
         var xhr = xhrFactory.apply(this, arguments); 
         function handler() { 
          options.onreadystatechange(xhr, jqXHR); 
         } 
         if (xhr.addEventListener) { 
          xhr.addEventListener("readystatechange", handler, false); 
         } else { 
          setTimeout(function() { 
           var internal = xhr.onreadystatechange; 
           if (internal) { 
            xhr.onreadystatechange = function() { 
             handler(); 
             internal.apply(this, arguments); 
            }; 
           } 
          }, 0); 
         } 
         return xhr; 
        }; 
       } 
      }); 

и образец Ajax запроса:

$.ajax({ 
        url: "test.php", 
        cache: false, 
        onreadystatechange: function(xhr) { 
         res = xhr.responseText.split("#"); 
         $("#id").html(res[res.length-1] + "% done<br/>"); 
        }     
       }).done(function(data) { 
         $("#id").append("all done!</br>"); 
        }); 
      }); 

протестирована с JQuery 1.5+

+0

это помогло мне, спасибо. знаете ли вы какую-либо проблему совместимости с кроссбраузерами с этими кодами? – littlealien