获取浏览器是否繁忙

发布于 2024-10-03 10:49:11 字数 349 浏览 2 评论 0原文

我正在尝试找到一种方法来获取浏览器当前是否正忙于 JavaScript。我正在考虑制作一个 Firefox 扩展,以在当前页面正在加载某些内容(通过 ajax 或只是正常页面加载)时注入布尔值或其他内容,或者使用 Greasemonkey 脚本或通过某些 JavaScript API(这将是最好的解决方案,但据我所知,不存在这样的解决方案)。

我想知道做到这一点的最佳方法是什么。我一直在寻找 Firefox Addon / Greasemonkey 教程来制作类似的东西,但找不到任何东西。有谁有任何提示或资源可以为我指出或更好的解决方案来解决这个问题?

谢谢

编辑:由于忙碌,我主要只需要知道浏览器是否正在从服务器发送或接收数据。

I'm trying to find a way to get if the browser is currently busy from JavaScript. I'm looking at making a Firefox extension to inject a Boolean value or something if the current page is loading something (either through ajax or just normal page loads), or the same with a Greasemonkey script, or through some JavaScript API (this would be the best solution, but from what I can see, nothing of the sort exists).

I was wondering what the best way to do this would be. I've been looking for Firefox Addon / Greasemonkey tutorials for making something like this and can't find anything. Does anyone have any tips or resources they could point me towards or better solutions for solving this?

Thanks

Edit: and by busy, I mostly just need to know if the browser is sending or receiving data from a server.

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

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

发布评论

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

评论(3

南渊 2024-10-10 10:49:11

jQuery,一个用于 DOM 操作和执行 ajax 调用的出色 javascript 框架,提供了两个出色的钩子来确定 ajax 调用何时正在进行:

$.ajaxStart()$.ajaxStop()

这两个钩子都采用一个处理函数,当 ajax 调用即将发生时,该函数将被调用分别在开始时和所有 ajax 调用停止时。这些函数可以绑定到页面上的任何元素。您可以在 $.ajaxStart() 处理程序中将全局布尔值设置为 true,并在 $.ajaxStop() 处理程序中将其设置回 false。

然后,您可以检查该布尔标志并确定 ajax 调用是否正在进行。

沿着这些思路:

$(document).ajaxStart(function() {
    window.ajaxBusy = true;
});

$(document).ajaxStop(function() {
    window.ajaxBusy = false;
});

就确定浏览器何时加载当前页面而言,您可以检查
document.readyState。当文档加载时,它返回一个 "loading" 字符串,加载后返回一个 "complete" 字符串。您可以将处理程序绑定到 document.onreadystatechange 并设置一个全局布尔值来指示文档是否仍在加载。

像这样的东西:

document.onreadystatechange = function() {
    switch (document.readyState) {
        case "loading":
            window.documentLoading = true;
            break;
        case "complete":
            window.documentLoading = false;
            break;
        default:
            window.documentLoading = false;
    }
}   

编辑:

看来 $.ajaxStart()$.ajaxStop() 不适用于没有 jQuery 的 ajax 调用。所有 XMLhttprequest 对象都有一个名为 readystatechange 的事件,您可以将处理程序附加到该事件。您可以利用此功能来确定单个呼叫是否完成。您可以将对未完成调用的所有引用推送到数组上,并在 setInterval() 中检查该数组的长度。如果它> 1、存在未决的ajax调用。这是一种粗略的方法,而且只是实现这一目标的一种方法。可能还有其他方法可以做到这一点。但一般方法如下:

// declare array to hold references to outstanding requets
window.orequets = [];

var req = XMLHttpRequest(); 
// open the request and send it here....
// then attach a handler to `onreadystatechange`
req.onreadystatechange = function() {
    if (req.readyState != 4 || req.readyState != 3) {
        // req is still in progress
        orequests.push(req);
        window.reqPos = orequests.length -1
    } else {
        window.orequests = orequests.slice(reqPos, reqPos + 1);
    }
}

对您将发送的每个 XMLHttpRequest() 执行上述操作,当然还要更改每个请求的名称。然后运行一个 setInterval(),每 x 毫秒运行一次,并检查 orquests 的长度属性。如果它等于零,则没有请求发生,如果它大于零,则请求仍在发生。如果没有请求发生,您可以通过 clearInterval() 清除间隔或保持其运行。

你的 setInterval 可能看起来像这样:

var ajaxInterval = setInterval(function() {
    if (orequests.length > 0) {
      // ajax calls are in progress
      window.xttpBusy = true;
    } else {
      // ajax calls have ceased
      window.xttpBusy = false;
      // you could call clearInterval(ajaxInterval) here but I don't know if that's your intention
    },
    3000 // run every 3 seconds. (You can decide how often you want to run it)
}); 

jQuery, a great javascript framework for DOM manipulation and performing ajax calls, provides two great hooks for determining when ajax calls are in progress:

$.ajaxStart() and $.ajaxStop()

Both of these hooks take a handler function that will be called when an ajax call is about to start, and when all ajax calls have ceased, respectively. These functions can be bound to any element on the page. You could set a global boolean value in your $.ajaxStart() handler to true and set it back to false in your $.ajaxStop() handler.

You could then check that boolean flag and determine whether ajax calls are in progress.

Something along these lines:

$(document).ajaxStart(function() {
    window.ajaxBusy = true;
});

$(document).ajaxStop(function() {
    window.ajaxBusy = false;
});

As far as determining when the browser is loading the current page, you could check
document.readyState. It returns a string of "loading" while the document is loading and a string of "complete" once it has loaded. You can bind a handler to document.onreadystatechange and set a global boolean that will indicate whether the document is still loading or not.

Something like this:

document.onreadystatechange = function() {
    switch (document.readyState) {
        case "loading":
            window.documentLoading = true;
            break;
        case "complete":
            window.documentLoading = false;
            break;
        default:
            window.documentLoading = false;
    }
}   

EDIT:

It appears that $.ajaxStart() and $.ajaxStop() do NOT work for ajax calls invoked without jQuery. All XMLhttprequest objects have an event called readystatechange that you can attach a handler to. You could utilize this functionality to determine whether or not that individual call is done. You could push all references to outstanding calls onto an array, and in a setInterval() check that array's length. If it > 1, there are out standing ajax calls. It's a rough approach, and only one way of getting about it. There are probably other ways to do this. But here's the general approach:

// declare array to hold references to outstanding requets
window.orequets = [];

var req = XMLHttpRequest(); 
// open the request and send it here....
// then attach a handler to `onreadystatechange`
req.onreadystatechange = function() {
    if (req.readyState != 4 || req.readyState != 3) {
        // req is still in progress
        orequests.push(req);
        window.reqPos = orequests.length -1
    } else {
        window.orequests = orequests.slice(reqPos, reqPos + 1);
    }
}

Do the above for each XMLHttpRequest() you will be sending, of course changing the request name for each one. Then run a setInterval() that runs every x amount of milliseconds, and checks the length property of orequests. If it is equal to zero, no requests are happening, if it is greater than zero, requests are still happening. If no requests are happening, you can either clear the interval through clearInterval() or keep it running.

Your setInterval might look something like this:

var ajaxInterval = setInterval(function() {
    if (orequests.length > 0) {
      // ajax calls are in progress
      window.xttpBusy = true;
    } else {
      // ajax calls have ceased
      window.xttpBusy = false;
      // you could call clearInterval(ajaxInterval) here but I don't know if that's your intention
    },
    3000 // run every 3 seconds. (You can decide how often you want to run it)
}); 
弥枳 2024-10-10 10:49:11

这就是我想我最终会做的事情。此解决方案类似于 Alex 建议的 Jquery 事件解决方案,不同之处在于它适用于任何使用 XMLHttpRequest(包括 Jquery)的内容:

var runningAjaxCount = 0;

var oldSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function() {
    oldOnReady = this.onreadystatechange;
    this.onreadystatechange = function() {
        oldOnReady.call(this);
        if(this.readyState == XMLHttpRequest.DONE) {
            ajaxStopped();
        }
    }
    ajaxStarted();
    oldSend.apply(this, arguments);
}

function ajaxStarted() {
    runningAjaxCount++;
}

function ajaxStopped() {
    runningAjaxCount--;
}

function isCallingAjax() {
    return runningAjaxCount > 0;
}

function isBrowserBusy() {
    return document.readyState != "complete" && isCallingAjax();
}

Here's what I think I'll end up doing. This solution is like the one Alex suggested with the Jquery events, except that it works with anything that uses the XMLHttpRequest (Including Jquery):

var runningAjaxCount = 0;

var oldSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function() {
    oldOnReady = this.onreadystatechange;
    this.onreadystatechange = function() {
        oldOnReady.call(this);
        if(this.readyState == XMLHttpRequest.DONE) {
            ajaxStopped();
        }
    }
    ajaxStarted();
    oldSend.apply(this, arguments);
}

function ajaxStarted() {
    runningAjaxCount++;
}

function ajaxStopped() {
    runningAjaxCount--;
}

function isCallingAjax() {
    return runningAjaxCount > 0;
}

function isBrowserBusy() {
    return document.readyState != "complete" && isCallingAjax();
}
小红帽 2024-10-10 10:49:11

从技术上讲,浏览器从来都不是“忙”的。商业是一个非常主观的术语。我们假设主线程正在执行一个简单的 while 循环,该循环会阻止执行。这可以被认为是繁忙,但是如果您有这样的情况该怎么办:

function busy() {setTimeout(busy, 0);do_something();}
busy();

浏览器本身没有被阻止,因此页面是否“繁忙”非常不清楚。而且,这甚至还没有开始触及网络工作者和 Chrome 中的代码。

你将很难做到这一点,即使你这样做了,它也可能不会像你期望的那样工作。不过,祝你好运。

The browser technically isn't ever "busy". Business is a very subjective term. Let's assume that the main thread is performing a simple while loop which blocks execution. This could be considered busy, but what if you have something like this:

function busy() {setTimeout(busy, 0);do_something();}
busy();

The browser isn't being blocked (per se), so whether or not the page is "busy" is very unclear. Also, that doesn't even begin to touch on web workers and code in the chrome.

You're going to be hard-pressed to do this, and even if you do, it likely won't work how you expect it to. Good luck, nonetheless.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文