XMLHttpRequest 多次启动而不启动 onreadystatechange 函数 [英] XMLHttpRequest launches multiple times without initiating the onreadystatechange function

查看:40
本文介绍了XMLHttpRequest 多次启动而不启动 onreadystatechange 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有问题的用户脚本: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:&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);
}());

推荐答案

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

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:

  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>) 实例.
  1. Initially, readyState is not four, so found is false. Since pg starts at 0, doIndex(pg + 1) is called. Now, xhr1 gets overwritten by a new XHR instance.
  2. 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 the else 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 created xhr1 request.
      So, you're calling doIndex(pg+1) over and over again, which, once pg 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆