在页面之间导航时取消我的 XHR 请求时遇到问题.我有一个页面有 8 个请求被触发.我在单击当前页面之外的链接时取消它们.页面在等待下一个要加载的文档时停止.他们的 XHR 请求在开发人员工具中显示为已取消,但新文档停滞不前,好像在等待他们回来一样.
I'm having problems canceling my XHR requests when navigating between pages. I have a page that has 8 requests that get fired off. I cancel them on click of a link outside of the current page. The page stalls as it waits on the next document to load. They XHR requests appear as cancelled in developer tools, but the new document stalls as if it is waiting for them to come back.
在此处您可以看到页面已停止,即使所有其他请求都已取消.新页面是唯一待处理的请求...
Here you can see the page is stalled even though all the other requests are cancelled. The new page is the only pending request...
在这里您可以看到,一旦页面最终跳转,TTFB 为 52.52 秒.如果我在点击离开之前等待电话回来,那么跳跃是即时的.
And here you can see once the page finally did make the jump the TTFB is 52.52s. If I wait for the calls to come back before clicking away the jump is instant.
如果有帮助,这里是新页面最终加载后的标题...
Here are the headers for the new pages once it finally loads if that helps...
我使用以下 frankenstein 代码来管理 XHR 请求.我在底部有一个取消请求的 cancelAll 函数......
I use the following frankenstein code to manage XHR requests. I have a cancelAll function towards the bottom that aborts the requests...
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.我错过了什么?
The site uses jQuery, PHP, Zend Framework 2, and SQL, Apache. What am I missing?
解决以上两点中的任何一个都会破坏链条并可能解决问题:
Adressing either of the above two points breaks the chain and may fix the problem:
ignore_user_abort
默认为 FALSE
,但您可以使用非标准设置.在 php.ini
中将此设置改回 FALSE
或调用 ignore_user_abort(false)
在处理这些可中断请求的脚本中.ignore_user_abort
is FALSE
by default, but you could be using a non-standard setting. Change this setting back to FALSE
in you php.ini
or call ignore_user_abort(false)
in the scripts that handle these interruptible requests.缺点:脚本刚刚终止.任何正在进行的工作都会被丢弃,可能会使系统处于脏状态.
echo
操作.缺点:这些虚拟数据可能会破坏脚本的正常输出.在这里,脚本也可能使系统处于肮脏状态.
session_start()
上,脚本以写入模式打开会话文件,有效地获取了一个独占锁.使用同一会话的后续请求将被搁置,直到释放锁为止.当脚本终止时会发生这种情况,除非您明确关闭会话.调用 session_write_close()
或session_abort()
越早越好.session_start()
, the script opens the session file in write mode, effectively acquiring an exclusive lock on it. Subsequent requests that use the same session are put on hold until the lock is released. This happens when the script terminates, unless you close the session explicitely. Call session_write_close()
or session_abort()
as early as possible.缺点:关闭后,无法再写入会话(除非您重新打开会话,但这有点不雅的hack).脚本也会继续运行,可能会浪费资源.
Drawback: when closed, the session cannot be written anymore (unless you reopen the session, but this is somewhat inelegant a hack). Also the script does keep running, possibly wasting resources.
我绝对推荐最后一个选项.
I definitely recommend the last option.
这篇关于取消 PHP 应用程序中未决的 AJAX 请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!