JQuery ajax async 'true' заставляет мое веб-приложение зависать до тех пор, пока данные не будут возвращены

Я работаю над веб-приложением на основе PHP (которое я не создавал).

Я запускаю этот запрос ajax:

$.ajax({
    type: 'POST',
    url: "/potato/ajax.php?module=test_module",
    dataType: 'json',
    async: true,
    data: {
            start_ts: that.start_date,
            stop_ts: that.end_date, 
            submitted: true
    },
    beforeSend: function() {
        console.info('Start: ' + new Date().toLocaleString());
        // Show Chart Loading 
        that.qwChart.showLoading({ 
            color: '#00b0f0', 
            // text: that.returnNumWithPrecent(that.progress)
            text: that.qwChartProgress
        });

        // If data div isn't displayed
        if (!that.dataDisplayed) {
            // Show divs loading
            that.showMainDiv();
        } else {
            that.$qwTbody.slideUp('fast');
            that.$qwTbody.html('');
        }
    },
    complete: function(){},
    success: function(result){
        console.info('End: ' + new Date().toLocaleString());

        // Clear timer
        clearInterval(timer);

        // Set progressbar to 100%
        that.setProgressBarTo100();

        // Show Download Button
        that.downloadBtn.style.display = 'inline-block';

        // Insert Chart Data
        that.insertChartData(result);

        // Insert Table Data
        that.insertTableData(result);
    }
});

И по какой-то причине все мое веб-приложение застревает, пока оно не вернет данные. Я знаю, что по умолчанию для запросов ajax установлено значение true, но я все равно добавил его, чтобы убедиться, что это так. Если он асинхронный, он должен выполнять свою работу без зависания моего веб-приложения, я прав? В чем может быть проблема? Это проблема на стороне сервера? Как мне отладить эту ситуацию?

Обновлено: говоря «застрял», я имею в виду - когда я жду ответа после отправки вызова ajax, обновления страницы или параллельного открытия других страниц (только в моем веб-приложении) отображается белый экран загрузки. Всякий раз, когда вызов ajax возвращает данные - белая страница загружается на запрошенную страницу.

Данные возвращаются из файла PHP:

<?php 
require_once("/www/common/api/db.php");

    if (!empty($_POST['submitted'])) {

    // error_reporting(-1);
    // Users Array:
    $users      = get_qw_data($start_ts_to_date, $stop_ts_to_date);

    // Summary Array:
    $summary    = get_qw_summary($users);

    // QW Score Array:
    $qws        = get_qw_score($users);

    // Generate CSV Report files
    /* Remove old:*/ 
    if (!is_file_dir_exist($customer))
        create_qw_directory($customer);

    /* Report #1: */ users_apps_google_macros_ma($users['users'], $customer);
    /* Report #2: */ usage_and_qw_summary($summary, $customer);
    /* Report #3: */ qw_score($qws, $customer);
    /* Zip Files: */ zip_qw_files($customer);

    echo json_encode($qws);
}

Можете дать еще инфу, что "прижилось". Что именно происходит? Или не происходит, если кажется, что он застрял. Заблокирован ли весь браузер на время запроса? Сколько данных возвращается из запроса?

Rory McCrossan 16.05.2018 11:10

Попробуй все закомментировать внутри beforeSend, это что-то меняет? Возможно, qwChart. showLoading вызывает блокировку?

mulquin 16.05.2018 11:11
Как он застрял? Есть ли что-нибудь «блокирующее» в отношении UI / Frontend; являются ли другие запросы «ожидающими» до завершения этого запроса; ...? Вы используете сеансы PHP? Это главный кандидат на то, что другие запросы «застревают», потому что файл сеанса блокируется для записи, поэтому, пока один запущенный экземпляр скрипта открывает сеанс, всем остальным приходится ждать. (Решением для этого было бы как можно скорее вызвать session_write_close.)
CBroe 16.05.2018 11:14

@RoryMcCrossan Я отредактировал свой пост, если он все еще неясен, пожалуйста, обновите мой, и я постараюсь объяснить лучше.

W.Doch 16.05.2018 11:15

Такое поведение похоже на то, что ваш сервер ограничивает количество подключений и / или запросов, поступающих с вашего IP-адреса. Вы работаете на удаленном сервере или на локальном?

Rory McCrossan 16.05.2018 11:16

@RoryMcCrossan, это происходит как в моей локальной среде разработки, так и в производственной среде.

W.Doch 16.05.2018 11:22

@mulquin Я пробовал это, и это не решило проблему ...

W.Doch 16.05.2018 11:22

@CBroe Да, я использую сеансы (зарегистрированные пользователи имеют сеансы, сохраненные для проверки и т. д.)

W.Doch 16.05.2018 11:26

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

siraj pathan 16.05.2018 11:27

@sirajpathan нет. не сработало.

W.Doch 16.05.2018 11:28

Думаю, проблема может быть в коде, который выполняет загрузку страниц и т. д.

mulquin 16.05.2018 11:42

Или же это происходит во всех браузерах?

mulquin 16.05.2018 11:43

Вы пытались как можно скорее закрыть сеанс в своем сценарии, который обрабатывает этот запрос AJAX?

CBroe 16.05.2018 11:58

@CBroe РЕШЕНА! Я добавил session_write_close(); сразу после require_once("/www/common/api/db.php");, и все работает параллельно с вызовом ajax. Я действительно не понимаю, почему это происходит и как session_write_close решил это. Чтобы запросить файл url: "/potato/ajax.php?module=test_module", через ajax, мне НЕОБХОДИМ сеанс (без него: веб-приложение не может подтвердить меня как зарегистрированного пользователя). Значит, я просто прерываю сеанс? Итак, как теперь параллельно работают другие вещи, которые зависят от него? Как именно он заблокирован? При запуске чего-то в ajax - он блокирует сеанс? по какой причине?

W.Doch 16.05.2018 12:05

@CBroe Можете ли вы написать мне ответ, в котором подробно объясняется, что происходит за сеансом? Как именно сеанс работает в моем случае?

W.Doch 16.05.2018 12:06

Добавлен ответ с расширенным объяснением для вас ;-)

CBroe 16.05.2018 12:24
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
16
221
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сеансы PHP являются основным кандидатом для «зависания» других запросов, потому что файл сеанса блокируется для записи, поэтому, пока один запущенный экземпляр скрипта открывает сеанс, всем остальным приходится ждать.

Решение - как можно скорее вызвать в session_write_close.


Немного расширенное объяснение:

Механизм хранения данных сеанса по умолчанию - это просто файловая система. Для каждого активного сеанса PHP просто помещает файл в настроенный каталог сеанса и записывает в него содержимое $ _SESSION, чтобы его можно было прочитать оттуда при следующем запросе, который должен получить к нему доступ.

Теперь, если несколько экземпляров сценария PHP попытаются записать измененные данные сеанса в этот файл «одновременно», это, очевидно, будет иметь большой потенциал конфликта / ошибки.

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

По умолчанию это происходит, когда скрипт завершен. Но если у вас есть более длительные скрипты, это может легко привести к таким «блокирующим» эффектам, как вы здесь. Решение состоит в том, чтобы явно сказать PHP (через session_write_close): «Я закончил с сеансом здесь, с этого момента я не буду записывать в него какие-либо новые / измененные данные - поэтому не стесняйтесь снимать блокировку, чтобы следующий сценарий может начать чтение данных сеанса ».

Важно то, что вы делаете это только после того, как ваш скрипт завершит манипулирование любыми данными сеанса. Вы все еще можете читать из $ _SESSION во время остальной части скрипта, но вы больше не можете писать в него. (Так что что-нибудь вроде $_SESSION['foo'] = 'bar'; должно выйти из строя после того, как вы освободите сеанс.)

Если единственная цель сеанса на этом этапе (в этом конкретном сценарии) - это проверка аутентификации пользователя, то вы можете закрыть сеанс сразу после этого. Остальная часть скрипта может работать столько, сколько захочет, без блокирования доступа других скриптов к тому же сеансу.


Это не ограничивается запросами AJAX - это лишь одно из тех мест, где вы обычно замечаете подобные вещи в первую очередь, потому что в противном случае у вас обычно не так много запросов, использующих сеанс, выполняющийся «параллельно». Но если бы вы были к f.e. открыв долго работающий скрипт несколько раз на нескольких вкладках браузера, вы заметите там тот же эффект - на первой вкладке скрипт будет работать и выполнять свои функции, тогда как на следующих вкладках вы должны заметить, что эти запросы «зависают» как хорошо, пока предыдущий экземпляр сценария удерживает блокировку записи в сеансе.

as soon as one script instance accesses the session - everybody else, other requests (to the same script, or a different one also using the session), will have to wait, until the first script is done with the session, and the write lock gets released again. - значит, если я запустил скрипт, а другой пользователь (другой сеанс) попытается связаться с этим файлом, ему придется дождаться завершения моего скрипта?
W.Doch 16.05.2018 13:45

@RickSanchez, нет, это ограничено одним и тем же сеансом. Другой пользователь имеет другой идентификатор сеанса и, следовательно, другой файл, в котором хранится его информация о сеансе. Каждая сессия имеет свой собственный файл данных.

CBroe 16.05.2018 13:47

Другие вопросы по теме