function downloadUrl(url, callback) {
    Transition();
    var request = window.ActiveXObject ?
        new ActiveXObject('Microsoft.XMLHTTP') :
        new XMLHttpRequest;

    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            request.onreadystatechange = doNothing;
            callback(request, request.status);
        }
    };

    request.open('GET', url, true);
    request.send(null);
    Transition();
}

function Transition() {
    var xmlhttp = window.ActiveXObject ?
        new ActiveXObject('Microsoft.XMLHTTP') :
        new XMLHttpRequest;

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
            xmlhttp.onreadystatechange = doNothing;
            callback(xmlhttp, xmlhttp.status);
        }
    };

    xmlhttp.open("GET", "transition.php", true);
    xmlhttp.send();
}

Ах да, я пытаюсь использовать jQuery и включить переменную сеанса, а после выполнения другой функции jQuery выключить эту переменную сеанса с помощью вышеуказанного метода. transition.php - это файл, который включает и выключает переменную, а другая функция jQuery downloadUrl просто загружает файл формата XML.

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

0
PowerThree 16 Апр 2020 в 02:33

1 ответ

Лучший ответ

Обновление: исправлены некоторые формулировки вокруг onreadystatechange и readyState.

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

Ваш код выполняется в том порядке, в котором он написан, но асинхронные запросы не задерживают выполнение, поэтому от второго XMLHttpRequest до url срабатывает почти сразу и задолго до того, как первый Transition() сработает. завершенный.

Если вам нужно, чтобы что-то происходило последовательно, вам нужно вызвать последующие шаги из обработчика событий запроса onreadystatechange, который запускается при изменении состояния запроса. Код уже проверяет наличие readyState 4, что означает, что запрос выполнен. Таким образом, вызываемый там код запускается после завершения запроса.

Я не уверен, что делает часть вашего кода, возможно, он скопирован сюда вне контекста (например, что такое ваши callback и doNothing?).

Вот рабочий JSFiddle на основе вашего кода, использующий фиктивный URL для всех 3 запросов. Я включил кучу журналов, откройте консоль разработчика, чтобы увидеть, в каком порядке все запускается, запускается и завершается.

Идея состоит в том, чтобы передать обратный вызов первому Transition, который будет запущен после завершения этого запроса:

function downloadUrl() {
    Transition(foo);
}

Transition принимает обратный вызов как параметр и запускает его по завершении:

function Transition(callback) {

    // ... your code ... 

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
            if (callback) {
                callback();
            }
        }
    };

    // ... your code

}

Здесь foo() - это функция, которая выполняет фактическую загрузку url, в основном всего, что у вас есть в downloadUrl(), но без вызовов Transition.

Когда foo() завершится, вам нужно снова вызвать Transition, но на этот раз мы не хотим ничего запускать, когда это будет сделано, поэтому мы передаем false, что {{X3} } проверит и пропустит попытку выполнения.

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

0
Don't Panic 16 Апр 2020 в 02:55