XMLHttpRequest 在不启动 onreadystatechange 函数的情况下启动多次

XMLHttpRequest launches multiple times without initiating the onreadystatechange function

本文关键字:启动 情况下 onreadystatechange XMLHttpRequest 函数      更新时间:2023-09-26

有问题的用户脚本:http://userscripts.org/scripts/show/130532

在为它制作的网站更新到 HTML5 后,我不得不更新脚本。但是,现在有一个非常大的问题。当我启动包含 XMLHttpRequest 的脚本主函数时,它只是向控制台发送这些请求的垃圾邮件,直到浏览器崩溃。

现在,我在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);
}());

你正在使用多个变量,而没有在本地声明这些变量:

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是假的,恐怖开始了:
    • xhr1.onreadystatechange在请求期间多次触发。 pg < 15是假的,所以else块被评估,你在其中启动几个新的XHR(xhr2)请求...
    • 所有以前的 readystatechange 事件仍会触发,因为请求尚未完成。在每个事件处理程序中,您都在比较 xhr1.readyState 的值,该值是指上次创建的xhr1请求的状态
      因此,您一遍又一遍地调用doIndex(pg+1),一旦pg达到 15,就会创建新的 XHR(xhr2 )实例。

要解决此问题,请在函数中声明变量,并将整个onreadystatechange块包装在if (xhr1.readyState == 4)中(或使用onload而不是onreadystatechange)。

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

这基于答案有所帮助:

                    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);
                            }
                        }
                    };