XMLHttpRequest多次启动而不启动onreadystatechange功能

时间:2012-06-16 14:05:05

标签: javascript xmlhttprequest userscripts

相关用户说明:http://userscripts.org/scripts/show/130532

在为其制作的网站已更新为HTML5之后,我不得不更新脚本。但是,它现在有一个非常大的问题。当我启动包含XMLHttpRequest的脚本的main函数时,它只是使用这些请求阻塞控制台,直到浏览器崩溃。

现在,我在StackOverflow和Google中四处寻找可以帮助我的任何东西,但没有任何东西。

如果您继续尝试脚本,请小心,因为它会导致浏览器崩溃。或者至少,它在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:&nbsp;Done";
                    found = 1;
                    break;
                }
            }
        }
    }

    function doIndex(pg) {
        b = document.getElementById('shouldi');
        if (!is404 && b.checked === true) {
            cstatus.innerHTML = "Status:&nbsp;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:&nbsp;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:&nbsp;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):&nbsp;<input type="text" value="30" maxlength="3" size="3" id="timerbox">&nbsp;&nbsp;</td><td style="width: 33%">&nbsp;<center><font size="20" color="red" id="page">&nbsp;</font></center>&nbsp;</td><td style="width: 33%;text-align:left;">&nbsp;&nbsp;<span id="checkcheck"><label for="shouldi">Checking</label><input type="checkbox" id="shouldi" /></span>&nbsp;&nbsp;<span id="checkstatus">Status:&nbsp;</span></td></tr></tbody></table>';
    main.parentNode.insertBefore(ui, main);
    cstatus = document.getElementById('checkstatus');
    cstatus.innerHTML = "Status:&nbsp;Ready";
    document.getElementById('checkcheck').addEventListener("click", function () {
        if (ttt !== null) {
            clearTimeout(ttt);
            ttt = null;
        }
        setTimeout(function () {
            doIndex(0);
        }, 500);
    }, false);
}());

2 个答案:

答案 0 :(得分:4)

您正在使用多个变量而未声明这些本地

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事件处理程序,其中发生以下情况:

  1. 最初,readyState不是四,所以found是假的。由于pg从0开始,因此调用doIndex(pg + 1)。现在, xhr1会被新的XHR实例覆盖
  2. 这会继续,直到pg达到15.然后,pg < 15为false,恐怖开始:
    • xhr1.onreadystatechange在请求期间多次触发。 pg < 15为false,因此会评估else块,您可以在其中启动多个新的XHR(xhr2)请求...
    • 所有以前的readystatechange事件仍然被触发,因为请求尚未完成。在每个事件处理程序中,您要比较xhr1.readyState的值,该值指的是最后创建的xhr1请求的状态。
      因此,您一遍又一遍地调用doIndex(pg+1),一旦pg达到15,就会创建新的XHR(xhr2)实例。
  3. 要解决此问题,请在函数中声明变量,并将整个onreadystatechange块包装在if (xhr1.readyState == 4)中(或使用onload代替onreadystatechange)。

    function dIndex(pg) {
        var xhr1, xhr2;
        ...
        xhr1.onreadystatechange = function() {
            if (xhr1.readyState === 4) {
               /* ... */
            }
        };
        ...
    

答案 1 :(得分:0)

这对答案有帮助:

                    let signupRequest = new XMLHttpRequest();
                    let url = "signup/" + inputMobile.value;
                    signupRequest.open("GET", url, true);
                    signupRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                    signupRequest.send();

                    signupRequest.onreadystatechange = function () {
                        if (signupRequest.readyState === 4) {
                            hideLoading();
                            if (signupRequest.status === 200) {
                                console.log("OK: " + status + " --- " + signupRequest.response);
                            } else {
                                console.log("NOK: " + status + " --- " + signupRequest.response);
                            }
                        }
                    };