在PHP应用程序中取消挂起的AJAX请求?

时间:2015-07-09 21:23:22

标签: php mysql ajax zend-framework2 xmlhttprequest

我在浏览页面时取消XHR请求时遇到问题。我有一个页面,有8个请求被解雇。我点击当前页面外的链接取消它们。页面在等待下一个要加载的文档时停止。他们的XHR请求在开发人员工具中显示为已取消,但新文档暂停,就像它等待它们返回一样。

在这里,您可以看到即使所有其他请求都被取消,页面也会停止。新页面是唯一待处理的请求...

enter image description here

在这里你可以看到,一旦页面最终确实跳转到TTFB是52.52s。如果我在点击之前等待回叫,那么跳转是即时的。

enter image description here

以下是新页面最终加载后的标题,如果有帮助的话...... enter image description here

我使用以下frankenstein代码来管理XHR请求。我有一个取消所有请求的取消所有功能......

 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。我错过了什么?

2 个答案:

答案 0 :(得分:6)

可能的因果链

  1. 服务器没有意识到XHR请求被取消,因此相应的PHP进程继续运行
  2. 这些PHP进程使用会话,并阻止对此会话的并发访问,直到它们终止
  3. 可能的解决方案

    通过上述两点中的任何一点打破链条并解决问题:

    1. (a)ignore_user_abort默认为FALSE,但您可能使用的是非标准设置。将此设置更改回FALSE中的php.ini或在处理这些可中断请求的脚本中调用ignore_user_abort(false)
    2. 缺点:脚本刚终止。正在进行的任何工作都会被删除,可能会使系统处于脏状态。

      1. (b)默认情况下,在尝试向客户端发送信息之前,PHP不会检测到用户已中止连接。在长时间运行的脚本中定期执行echo项内容。
      2. 缺点:此伪数据可能会破坏脚本的正常输出。此处,脚本也可能使系统处于脏状态。

        1. PHP会话作为文件存储在服务器上。在session_start()上,脚本以写入模式打开会话文件,有效地获取其上的独占锁定。使用相同会话的后续请求将被暂停,直到锁定被释放。除非您明确关闭会话,否则在脚本终止时会发生这种情况。尽早致电session_write_close()session_abort()
        2. 缺点:当关闭时,会话不再被写入(除非你reopen the session,但这有点不优雅)。脚本也会继续运行,可能会浪费资源。

          我绝对推荐最后一个选项。

答案 1 :(得分:1)

您是否在变量上存储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()