如何在不重叠的情况下定时发起Ajax请求?

8

我想设置一个网页,通过AJAX调用从嵌入式Web服务器中采样数据。如何设置代码,以便一个请求不会与另一个请求重叠? 需要说明的是,我几乎没有JavaScript经验,而且有一个强烈的理由不使用任何大于10KB左右大小的外部库。


6
欢迎来到StackOverflow。非常好的第一个问题。 - Sampson
3个回答

6
您可能希望考虑在上一次AJAX调用成功响应后,重新发起AJAX请求的选项。
function autoUpdate()
{
    var ajaxConnection = new Ext.data.Connection();

    ajaxConnection.request(
    {
        method:         'GET',
        url:            '/web-service/', 

        success: function(response) 
        {
            // Add your logic here for a successful AJAX response.
            // ...
            // ...

            // Relaunch the autoUpdate() function in 5 seconds.
            setTimeout(autoUpdate, 5000);
        }
    }
}

这个例子使用了ExtJS,但你也可以很容易地使用XMLHttpRequest
注意:如果你必须要有一个精确的x秒间隔,你需要跟踪从AJAX请求发出到setTimeout()调用时经过的时间,并将其从延迟中减去。否则,在上面的例子中,间隔时间将随着网络延迟和处理Web服务逻辑的时间而变化。

不完全是他们所要求的,但使用回调函数是一个非常好的解决方案。 - Dan Beam
1
不错的答案。然而,您可能希望在之前的Ajax调用完成后setTimeout,无论成功与否。否则,第一次超时或错误时,您将停止获取更新。 - Grodriguez

1

AJAX,尽管名字中带有“异步”一词,但并不一定是异步的。

这里是异步方法...

var req;

function ajax(method,url,payload,action)
    {
    if (window.XMLHttpRequest)
        {
        req = new XMLHttpRequest();
        req.onreadystatechange = action;
        req.open(method, url, true);
        req.send(payload);
        }
    else if (window.ActiveXObject)
        {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req)
            {
            req.onreadystatechange = action;
            req.open(method, url, true);
            req.send(payload);
            }
        else
            {
            alert("Could not create ActiveXObject(Microsoft.XMLHTTP)");
            }
        }
    }

...但这里有一个同步的等效物...

function sjax(method,url,payload,action)
    {
    if (window.XMLHttpRequest)
        {
        req = new XMLHttpRequest();
        req.open(method, url, false);
        req.send(payload);
        action();
        }
    else if (window.ActiveXObject)
        {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req)
            {
            req.onreadystatechange = action;
            req.open(method, url, false);
            req.send(payload);
            }
        else
            {
            alert("Could not create ActiveXObject(Microsoft.XMLHTTP)");
            }
        }
    }

... 这里是一个典型的操作...

function insertHtml(target)
    {
    var pageTarget = arguments[0];
    if (req.readyState == 4) // 4 == "loaded"
        {
        if (req.status == 200) // 200 == "Ok"
            {
            if (req.responseText.indexOf("error") >= 0)
                {
                alert("Please report the following error...");
                pretty = req.responseText.substring(req.responseText.indexOf("error"),1200);
                pretty = pretty.substring(0,pretty.indexOf("\""));
                alert(pretty + "\n\n" + req.responseText.substring(0,1200));
                }
            else
                {
                div = document.getElementById(pageTarget);
                div.innerHTML = req.responseText;
                dimOff();
                }
            }
        else
            {
            alert("Could not retreive URL:\n" + req.statusText);
            }
        }
    }

同步请求并不是我认为最好的选择,因为它们会锁定页面的其他部分...但这取决于用户的需求。此外,根据jQuery $.ajax文档:“当需要同步时,最好通过其他方式阻止用户交互。” - Dan Beam

1

我建议您使用像jx.js这样的小型工具包(source)。您可以在这里找到它:http://www.openjs.com/scripts/jx/(压缩后不到1k)

设置请求:

jx.load('somepage.php', function(data){
    alert(data); // Do what you want with the 'data' variable.
});

要在间隔时间内设置它,您可以使用 setInterval 和一个变量来存储当前是否正在发生请求 - 如果是,则我们什么也不做:

var activeRequest = false;
setInterval(function(){

    if (!activeRequest) {
        // Only runs if no request is currently occuring:
        jx.load('somepage.php', function(data){
            activeRequest = false;
            alert(data); // Do what you want with the 'data' variable.
        });
    }
    activeRequest = true;

}, 5000); // Every five seconds

和另一个答案一样...所以为什么浪费时间间隔,不如进行同步调用。通过轮询平均会浪费5000ms/2。 - dacracot
我明白你的回答。这可以减少重叠并降低服务器负载。 - Khurram Shaikh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接