Подтвердить что ты не робот

Отменить ожидающие запросы AJAX в приложении PHP?

У меня возникают проблемы с отменой моих запросов XHR при навигации между страницами. У меня есть страница, на которой есть 8 запросов, которые увольняются. Я отменяю их при нажатии ссылки за пределами текущей страницы. Страница закрывается, так как она ждет следующего документа для загрузки. Запросы XHR отображаются как отмененные в инструментах разработчика, но новый документ заходит, как будто он ждет их возвращения.

Здесь вы можете увидеть, что страница застопорена, хотя все остальные запросы отменены. Новая страница - единственный ожидающий запрос...

enter image description here

И здесь вы можете увидеть, как только страница, наконец, сделала прыжок, TTFB - 52.52. Если я дождался, пока вызовы вернутся, прежде чем щелкнуть, переход мгновен.

enter image description here

Вот заголовки для новых страниц, когда они наконец загрузятся, если это поможет... enter image description here

Я использую следующий код frankenstein для управления запросами XHR. У меня есть функция cancelAll в нижней части, которая прерывает запросы...

 XHRManager = {
Requests: [],
pendingRequests: [],
addNextRequest: function (r) {
    var timeout = 0;
    if (trace.isDevelopment()) {
        timeout = 350;
    }
    setTimeout(function () {
        if (r.url ==  XHRManager.pendingRequests[0].url && r.start ==  XHRManager.pendingRequests[0].start) {
             XHRManager.pendingRequests.splice(0, 1);
        }
        else {
            $( XHRManager.pendingRequests).each(function (ii, dd) {
                if (dd.url == r.url && dd.start == r.start) {
                     XHRManager.pendingRequests.splice(ii, 1);
                }
            });
        }
         XHRManager.startNextRequest();
        if (trace.findLocalStorage()) {
             XHRManager.showTrace = true;
            trace.show();
        }
    }, timeout);
},
requests: [],
intervals: [],
requestsInt: 0,
firstRun: true,
delay: 500,
globalTimeout: 5000,
showTrace: false,
startNextRequest: function () {
    $( XHRManager.pendingRequests).each(function (i, d) {
        if (d.start) {

        }
        if (i == 0) {
            if (trace.domWatcher.constructor == Function) {
                trace.domWatcher(d.requestNumber);
            }
            trace.log("Request #" + d.requestNumber + " started");
            d.requestType(d);
        }
    });
    if ( XHRManager.pendingRequests.length == 0) {
        if (trace.isDevelopment()) {
            trace.show();
        }
    }
},
AddToPendingRequests: function (url, params, cb, type, errCB) {
    var rI =  XHRManager.requestsInt;
     XHRManager.requestsInt++;
    var req = {url: url, params: params, cb: cb, requestNumber: rI, requestType: type};
    if (errCB) {
        req.errCB = errCB;
    }
     XHRManager.pendingRequests.push(req);
    // if(trace.findLocalStorage()){
    //    trace.show();
    //  }
    if (rI == 0 ||  XHRManager.pendingRequests.length == 1) {
         XHRManager.startNextRequest();
    }
},
writeVals: function (url, params, data, start, cb, requestNumber) {
    if ($("meta[content='development']").length > 0) {
        try {
            var response = {};
            response.requestNumber = requestNumber;
            if (data.sql != "" && data.sql != undefined) {
                response.sql = data.sql;
            }
            if (data.debug) {
                if (data.debug.sql != "" && data.debug.sql != undefined) {
                    response.sql = data.debug.sql;
                }
            }
            if (data.data != "" && data.data != undefined) {
                response.data = data.data;
            }
            else {
                if (data != "" || data != undefined) {
                    response.data = data;
                }
            }
            if (url != "" && url != undefined) {
                response.url = url;
            }
            if (params != "" && params != undefined) {
                response.params = params;
            }
            if (cb) {
                response.cb = cb.toString();
            }
            else {
                response.cb = "";
            }
            response.requestStats = {};
            response.requestStats.start = start;
            response.requestStats.end = Date();
            response.requestStats.totalTime = ((new Date(response.requestStats.end)).getTime() - (new Date(start)).getTime()) / 1000 + " sec(s)";
             XHRManager.Requests.push(response);

        }
        catch (e) {
            trace.log(e);
        }
    }
},
_create: function (r) {
    var xm =  XHRManager;
    var start = Date();
    var req = $.get(r.url, r.params, r.cb)
        .done(function (data) {
             XHRManager.writeVals(r.url, r.params, data, start, r.cb, r.requestNumber);
            if (trace.isDevelopment() && trace.isOn()) {
                 XHRManager.addNextRequest(r);
            }
        });
    xm.requests.push(req);
},
_createAjax: function (r) {
    var xm =  XHRManager;
    var start = Date();
    if (r.type == "PUT" || r.type == "DELETE") {
        var req = $.ajax({
            type: r.type,
            xhrFields: {
                withCredentials: true
            },
            url: r.url,
            data: r.params,
            success: function (data) {
                 XHRManager.writeVals(r.url, r.params, r.data, r.start, r.cb, r.requestNumber);
                r.cb(data);
                if (trace.isDevelopment() && trace.isOn()) {
                     XHRManager.addNextRequest(r);
                }
            },
            error: r.errCB
        });
        xm.requests.push(req);
    }
    else {
        var req = $.ajax({
            type: r.type,
            xhrFields: {
                withCredentials: true
            },
            dataType: 'json',
            json: 'json',
            url: r.url,
            data: r.params,
            success: function (data) {
                 XHRManager.writeVals(r.url, r.params, data, start, r.cb, r.requestNumber);
                r.cb(data);
                if (trace.isDevelopment() && trace.isOn()) {
                     XHRManager.addNextRequest(r);
                }
            },
            error: r.errCB
        });
        xm.requests.push(req);
    }
},
_createJSON: function (r) {
    var start = Date();
    var xm =  XHRManager;
    var req = $.getJSON(r.url, r.params, r.cb)
        .done(function (data) {
             XHRManager.writeVals(r.url, r.params, data, start, r.cb, r.requestNumber);
            if (trace.isDevelopment() && trace.isOn()) {
                 XHRManager.addNextRequest(r);
            }
        });
    xm.requests.push(req);
},
create: function (url, params, cb) {
    if (trace.isDevelopment() && trace.isOn()) {
         XHRManager.AddToPendingRequests(url, params, cb,  XHRManager._create);
    }
    else {
        var r = {};
        r.url = url;
        r.params = params;
        r.cb = cb;
         XHRManager._create(r);
    }
},
createAjax: function (url, params, type, cb, errCB) {
    if (trace.isDevelopment() && trace.isOn()) {
         XHRManager.AddToPendingRequests(url, params, cb,  XHRManager._createAjax, errCB);
    }
    else {
        var r = {};
        r.url = url;
        r.params = params;
        r.cb = cb;
        r.type = type;
        r.errCB = errCB;
         XHRManager._createAjax(r);
    }

},
createJSON: function (url, params, cb) {
    if (trace.isDevelopment() && trace.isOn()) {
         XHRManager.AddToPendingRequests(url, params, cb,  XHRManager._createJSON);
    }
    else {
        var r = {};
        r.url = url;
        r.params = params;
        r.cb = cb;
         XHRManager._createJSON(r);
    }
},
remove: function (xhr) {
    var xm =  XHRManager;
    var index = xm.requests.indexOf(xhr);
    if (index > -1) {
        xm.requests.splice(index, 1);
    }
    index = xm.intervals.indexOf(xhr.interval);
    if (index > -1) {
        xm.intervals.splice(index, 1);
    }
},
cancelAll: function () {
    var xm =  XHRManager;
    $(xm.requests).each(function () {
        var t = this;
        t.abort();
    });
    $(xm.intervals).each(function () {
        var t = this;
        clearInterval(t);
    });
    xm.requests = [];
    xm.intervals = [];
}
};

На сайте используются jQuery, PHP, Zend Framework 2 и SQL, Apache. Что мне не хватает?

4b9b3361

Ответ 1

Вероятная причинная цепочка

  • сервер не понимает, что запросы XHR отменены, поэтому соответствующие процессы PHP продолжают работать
  • эти процессы PHP используют сеансы и предотвращают одновременный доступ к этому сеансу до тех пор, пока они не завершат

Возможные решения

Адресация одной из двух вышеуказанных точек разбивает цепочку и может решить проблему:

  • (a) ignore_user_abort по умолчанию FALSE, но вы можете использовать нестандартную настройку. Измените этот параметр на FALSE в php.ini или вызовите ignore_user_abort(false) в сценариях, которые обрабатывают эти прерываемые запросы.

Недостаток: script просто завершается. Выполняется любая работа, возможно, что система находится в грязном состоянии.

  • (b) По умолчанию PHP не обнаружит, что пользователь прервал соединение до тех пор, пока не будет предпринята попытка отправить информацию клиенту. Выполняйте echo что-то периодически в течение долгого времени script.

Недостаток: эти фиктивные данные могут повредить нормальный вывод вашего script. И здесь тоже script может оставить систему в грязном состоянии.

  1. Сессии PHP хранятся в виде файла на сервере. На session_start() script открывает файл сеанса в режиме записи, фактически приобретая эксклюзивную блокировку. Последующие запросы, которые используют один и тот же сеанс, приостанавливаются до тех пор, пока блокировка не будет отпущена. Это происходит, когда script завершается, если вы не закрываете сеанс явно. Вызовите session_write_close() или session_abort() как можно раньше насколько это возможно.

Недостаток: при закрытии сеанс больше не может быть записан (если вы не открываете сеанс, но это несколько неэлегантный взлом). Кроме того, script продолжает работать, возможно, тратя ресурсы.

Я определенно рекомендую последний вариант.

Ответ 2

Записываете ли вы свой запрос Ajax на переменную?. Если нет, то что вам нужно сделать, чтобы полностью отменить запрос

var xhr = $.ajax({
    type: "POST",
    url: "anyScript.php",
    data: "data1=0&data2=1",
    success: function(msg){
       //Success Function
    }
});

//here you abort the request
xhr.abort()

Ответ 3

Я предполагаю, что вы это сделали, но проверьте все файлы журнала (php и apache).

Также попробуйте следующее:

php.ini

upload_max_filesize = 256M
post_max_size = 256M

.htaccess

php_value upload_max_filesize 256M
php_value post_max_size 256M

Еще одна вещь, которая меня беспокоит, - это эта часть.

$(xm.requests).each(function () {
    var t = this;
    t.abort();
});
$(xm.intervals).each(function () {
    var t = this;
    clearInterval(t);
});

Попробуйте передать аргументы для обратного вызова и прервать их. Я видел случаи, когда присвоение this переменной, содержащей цикл $.each, фактически указывает на другой объект или глобальное окно.

$(xm.requests).each(function (index, value) {
        value.abort();
    });
    $(xm.intervals).each(function (index, value) {
        clearInterval(value);
    });