我的 AJAX、Greasemonkey 脚本中出现间歇性行为

发布于 2024-12-11 16:32:32 字数 2910 浏览 0 评论 0原文

我有一个小型 Greasemonkey 脚本,不包含任何随机部分,但其结果会随着每次页面重新加载而变化。

我是一个菜鸟,我可能做错了什么,但我不知道是什么。我希望你能帮助我。

代码太大,写得太差,无法在此处重现,因此我将尝试总结我的情况:

  • 我有一个链接列表,其中包含 href=javascript:void(0) 和 <代码>onclick=f(link_id)。
  • f(x) 向服务器发出 XML HTTP 请求,并返回链接地址。
  • 我的脚本旨在预先计算 f(x) 并在页面加载时更改 href 值。

我有一个函数 wait() 等待页面加载,然后有一个函数 findLinks() 获取要更改的节点(使用 xpath)。< br> 然后是一个将 xhr 发送到服务器的函数 sendRequest()。最后,handleRequest() 异步 (r.onreadystatechange) 检索响应,并设置先前找到的节点。

你觉得这个想法有什么问题吗?

使用网络分析器,我可以看到请求总是发送得很好,响应也是如此。

有时,href 值会更改,但有时对于某些链接,它不会更改,仍保持 javascript:void(0)

我真的不明白为什么它只有一半的时间有效......

function getUrlParameterFromString(urlString, name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(urlString);
    if (results == null) {
        return "";
    } else {
        return results[1];
    }
}

function getUrlParameter(name) {
    return getUrlParameterFromString(window.location.href, name);
}

function wait() {

    var findPattern = "//a";
    var resultLinks = document.evaluate(findPattern, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

    if (resultLinks == null || resultLinks.snapshotLength == 0) {
        return setTimeout(_wait, 100);

    } else {
        for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
            var node = resultLinks.snapshotItem(i);
            var s = node.getAttribute('onclick');
            var linkId = s.substring(2, s.length - 1); // f(x)->x
            sendRequest(linkId, node);
        }
    }
}

function sendRequest(linkId, nodeToModify) {

    window.XMLHttpRequest ? r = new XMLHttpRequest : window.ActiveXObject && (r = new ActiveXObject("Microsoft.XMLHTTP"));

    if (r) {
        r.open("POST", "some_url", !0);
        r.onreadystatechange = function () {
            handleRequest(nodeToModify, linkId, r);
        }
        r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        r.send(linkId);
    }

}

function handleRequest(nodeToModify, num, r) {
 if (r.readyState == 4) {
     if (r.status == 200) {
         console.log('handleRequest() used');
         var a = r.responseText;
         if (a == null || a.length < 10) {
             sendRequest(num, nodeToModify);
         } else {
             var url = unescape((getUrlParameterFromString(a, "url")).replace(/\+/g, " "));
             nodeToModify.setAttribute('href', url);
             nodeToModify.setAttribute('onclick', "");
         }
     } else {
         alert("An error occurred: " + r.statusText)
     }
 }

}

wait();

I've a small Greasemonkey script that doesn't include any random part, but its results change with each page reload.

I'm a noob and I'm probably doing something wrong, but I don't know what. I hope you'll be able to help me.

The code is too large and too poorly written to be reproduced here, so I'll try to sum up my situation:

  • I have a list of links which have href=javascript:void(0) and onclick=f(link_id).
  • f(x) makes an XML HTTP request to the server, and returns the link address.
  • My script is meant to precompute f(x) and change the href value when the page loads.

I have a function wait() that waits for the page to load, then a function findLinks() that gets the nodes that are to be changed (with xpath).
Then a function sendRequest() that sends the xhr to the server. And, finally handleRequest() that asynchronously (r.onreadystatechange) retrieves the response, and sets the nodes previously found.

Do you see anything wrong with this idea?

Using a network analyzer, I can see that the request is always sent fine, and the response also.

Sometimes the href value is changed, but sometimes for some links it isn't and remains javascript:void(0).

I really don't see why it works only half the time...

function getUrlParameterFromString(urlString, name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(urlString);
    if (results == null) {
        return "";
    } else {
        return results[1];
    }
}

function getUrlParameter(name) {
    return getUrlParameterFromString(window.location.href, name);
}

function wait() {

    var findPattern = "//a";
    var resultLinks = document.evaluate(findPattern, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

    if (resultLinks == null || resultLinks.snapshotLength == 0) {
        return setTimeout(_wait, 100);

    } else {
        for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
            var node = resultLinks.snapshotItem(i);
            var s = node.getAttribute('onclick');
            var linkId = s.substring(2, s.length - 1); // f(x)->x
            sendRequest(linkId, node);
        }
    }
}

function sendRequest(linkId, nodeToModify) {

    window.XMLHttpRequest ? r = new XMLHttpRequest : window.ActiveXObject && (r = new ActiveXObject("Microsoft.XMLHTTP"));

    if (r) {
        r.open("POST", "some_url", !0);
        r.onreadystatechange = function () {
            handleRequest(nodeToModify, linkId, r);
        }
        r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        r.send(linkId);
    }

}

function handleRequest(nodeToModify, num, r) {
 if (r.readyState == 4) {
     if (r.status == 200) {
         console.log('handleRequest() used');
         var a = r.responseText;
         if (a == null || a.length < 10) {
             sendRequest(num, nodeToModify);
         } else {
             var url = unescape((getUrlParameterFromString(a, "url")).replace(/\+/g, " "));
             nodeToModify.setAttribute('href', url);
             nodeToModify.setAttribute('onclick', "");
         }
     } else {
         alert("An error occurred: " + r.statusText)
     }
 }

}

wait();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

居里长安 2024-12-18 16:32:32

看起来该脚本将恰好更改 1 个链接。查找“闭包”; 此循环:

for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
    var node = resultLinks.snapshotItem(i);
    var s = node.getAttribute('onclick');
    var linkId = s.substring(2, s.length - 1); // f(x)->x
    sendRequest(linkId, node);
}

需要一个闭包,以便 sendRequest() 获得正确的值。否则,只会修改最后一个链接。

尝试:

for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
    var node = resultLinks.snapshotItem(i);
    var s = node.getAttribute('onclick');
    var linkId = s.substring(2, s.length - 1); // f(x)->x

    //-- Create a closure so that sendRequest gets the correct values.
    ( function (linkId, node) {
            sendRequest (linkId, node);
        }
    )(linkId, node);
}

It looks like that script will change exactly 1 link. Look-up "closures"; this loop:

for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
    var node = resultLinks.snapshotItem(i);
    var s = node.getAttribute('onclick');
    var linkId = s.substring(2, s.length - 1); // f(x)->x
    sendRequest(linkId, node);
}

needs a closure so that sendRequest() gets the correct values. Otherwise, only the last link will be modified.

Try:

for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
    var node = resultLinks.snapshotItem(i);
    var s = node.getAttribute('onclick');
    var linkId = s.substring(2, s.length - 1); // f(x)->x

    //-- Create a closure so that sendRequest gets the correct values.
    ( function (linkId, node) {
            sendRequest (linkId, node);
        }
    )(linkId, node);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文