XMLHttpRequest 多次启动而不启动 onreadystatechange 函数 [英] XMLHttpRequest launches multiple times without initiating the onreadystatechange function
问题描述
有问题的用户脚本:http://userscripts.org/scripts/show/130532
在网站更新到 HTML5 后,我不得不更新脚本.然而,它现在有一个非常大的问题.当我启动包含 XMLHttpRequest 的脚本的 main 函数时,它只是用这些请求向控制台发送垃圾邮件,直到浏览器崩溃为止.
After the site it's been made for has been updated to HTML5, I had to update the script. However, it's got a really big problem now. When I launch the script's main function that contains the XMLHttpRequest, it simply spams the console with these requests until the browser simply crashes.
现在,我在 StackOverflow 和 Google 中四处寻找任何可以帮助我的东西,但一无所获.
Now, I looked around in both StackOverflow and in Google for anything that could help me, but there's nothing.
如果您继续尝试该脚本,请小心,因为它会导致浏览器崩溃.或者至少,它在 FF 11.00 中对我有用
If you proceed to try the script, be careful, because it crashes the browser. Or at least, it does for me in FF 11.00
代码:
// ==UserScript==
// @name Where my thread at
// @include *//boards.4chan.org/*/res/*
// ==/UserScript==
(function () {
"use strict";
var board = document.location.href.match(/https?:\/\/boards\.4chan\.org\/[\w]+/i), threadNo = location.pathname.match(/\/res\/([\d]+)/i), main = document.getElementsByName("delform")[0], is404 = 0, ttt = null, b, c, num, timer, html, i, l, no, found, xhr1, xhr2, cstatus, ui, pg;
function lookup(resp) {
html = resp.match(/<div class="postContainer opContainer".*?<\/div>[^<]*?<\/div>/gi);
if (html) {
l = html.length;
for (i = 0; i < l; i += i) {
no = html[i].match(/<a href="res\/([\d]+)"/i)[1];
if (threadNo[1] === no) {
document.getElementById('page').innerHTML = pg;
cstatus.innerHTML = "Status: Done";
found = 1;
break;
}
}
}
}
function doIndex(pg) {
b = document.getElementById('shouldi');
if (!is404 && b.checked === true) {
cstatus.innerHTML = "Status: Searching";
c = document.getElementById('timerbox');
num = parseInt(c.value, 10);
if (num > 600) { timer = 600; }
if (num < 30) { timer = 30; }
if (isNaN(num)) {
timer = 60;
alert("Value entered is not a valid number! Defaulting to 60");
c.value = "60";
}
if (!timer) { timer = num; }
xhr1 = new XMLHttpRequest();
xhr1.open("GET", board[0] + (0 === pg ? "" : "/" + pg), true);
xhr1.setRequestHeader("Cache-Control", "no-cache");
xhr1.onreadystatechange = function () {
if (xhr1.readyState === 4) {
if (xhr1.status === 200) {
lookup(xhr1.responseText);
}
}
if (found) {
ttt = setTimeout(function () {
doIndex(0);
}, timer * 1000);
} else {
if (pg < 15) {
doIndex(pg + 1);
} else {
cstatus.innerHTML = "Status: Really 404?";
xhr2 = new XMLHttpRequest();
xhr2.open("GET", board[0] + threadNo[0], true);
xhr2.setRequestHeader("Cache-Control", "no-cache");
xhr2.onreadystatechange = function () {
if (xhr2.readyState === 4) {
if (xhr2.status === 404) {
cstatus.parentNode.removeChild(cstatus);
document.getElementById('page').innerHTML = "404'd";
is404 = 1;
} else {
cstatus.innerHTML = "Status: Still alive";
setTimeout(function () {
doIndex(0);
}, 1000);
}
}
};
xhr2.send(null);
}
}
};
xhr1.send(null);
}
}
ui = document.createElement('center');
ui.innerHTML = '<table border="0" style="width: 100%"><tbody><tr><td style="width: 33%;text-align: right;">Timer(600-30s): <input type="text" value="30" maxlength="3" size="3" id="timerbox"> </td><td style="width: 33%"> <center><font size="20" color="red" id="page"> </font></center> </td><td style="width: 33%;text-align:left;"> <span id="checkcheck"><label for="shouldi">Checking</label><input type="checkbox" id="shouldi" /></span> <span id="checkstatus">Status: </span></td></tr></tbody></table>';
main.parentNode.insertBefore(ui, main);
cstatus = document.getElementById('checkstatus');
cstatus.innerHTML = "Status: Ready";
document.getElementById('checkcheck').addEventListener("click", function () {
if (ttt !== null) {
clearTimeout(ttt);
ttt = null;
}
setTimeout(function () {
doIndex(0);
}, 500);
}, false);
}());
推荐答案
您正在使用多个变量而没有声明这些本地:
You're using several variables without declaring these locally:
var ..., found, xhr1, xhr2, cstatus, ui, pg;
...
function doIndex(pg) {
...
xhr1 = new XMLHttpRequest();
// ^^^^ No var !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
...
xhr1.onreadystatechange = function() {
if (xhr1.readyState === 4) { ... }
if (found) {
...
} else {
if (pg < 15) {
doIndex(pg + 1); // <-- !!!!!!!!!!!!!!!!!!
} else { ...
xhr2 = new XMLHttpRequest();
...
xhr2.onreadystatechange = function() { ... };
xhr2.send(null);
}
}
};
xhr1.send(null);
}
} ...
doIndex(0); // Initiate the doom
首先,您将一个新的 XHR 实例分配给一个非本地 xhr1
变量.
然后,添加一个 readystatechange
事件处理程序,其中发生以下情况:
First, you assign a new XHR instance to a non-local xhr1
variable.
Then, you add a readystatechange
event handler, in which the following happens:
- 最初,
readyState
不是四,所以found
是假的.由于pg
从 0 开始,doIndex(pg + 1)
被调用.现在,xhr1
被新的 XHR 实例覆盖. - 这样继续下去,直到
pg
达到 15.然后,pg <;15
为假,恐怖开始:xhr1.onreadystatechange
在请求期间多次触发.<代码>pg <15 为假,因此会评估else
块,在其中启动几个新的 XHR (xhr2
) 请求...- 所有之前的 readystatechange 事件仍然被触发,因为请求还没有完成.在每个事件处理程序中,您都在比较
xhr1.readyState
的值,该值指的是 最后 创建的xhr1
请求的状态强>.
因此,您一遍又一遍地调用doIndex(pg+1)
,一旦pg
达到 15,就会创建新的 XHR (xhr2
>) 实例.
- Initially,
readyState
is not four, sofound
is false. Sincepg
starts at 0,doIndex(pg + 1)
is called. Now,xhr1
gets overwritten by a new XHR instance. - This continues, until
pg
reaches 15. Then,pg < 15
is false, and the horror starts:xhr1.onreadystatechange
fires multiple time during the request.pg < 15
is false, so theelse
block is evaluated, in which you launch several new XHR (xhr2
) requests...- All of the previous readystatechange events are still fired, because the requests haven't finished yet. In every event handler, you're comparing the value of
xhr1.readyState
, which refers to the state of the last createdxhr1
request.
So, you're callingdoIndex(pg+1)
over and over again, which, oncepg
has reached 15, creates new XHR (xhr2
) instances.
要解决这个问题,在函数中声明变量,并将整个 onreadystatechange
块包裹在 if (xhr1.readyState == 4)
中(或使用 onload
而不是 onreadystatechange代码>).
To fix the problem, declare the variables in the function, and wrap the whole onreadystatechange
block in if (xhr1.readyState == 4)
(or use onload
instead of onreadystatechange
).
function dIndex(pg) {
var xhr1, xhr2;
...
xhr1.onreadystatechange = function() {
if (xhr1.readyState === 4) {
/* ... */
}
};
...
这篇关于XMLHttpRequest 多次启动而不启动 onreadystatechange 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!