繁体   English   中英

对同一URL的多个Ajax请求的异常行为

[英]Strange behavior with multiple ajax requests to the same URL

我在CherryPy服务器中构造了一个奇怪的情况,我希望得到一些帮助来了解确切的情况以及原因。 这是server.py

import cherrypy
import os
import threading

class Root(object):
    def __init__(self):
        self.count = 0;
        self.lock = threading.Lock()

    @cherrypy.expose
    def app(self):
        with self.lock:
            self.count += 1
        return "Call #%d" % (self.count)

if __name__ == '__main__':
    cherrypy.quickstart(Root(), "/", {"/": { "tools.staticdir.on": True,
                                             "tools.staticdir.dir": os.getcwd() } })

这是一个非常简单的应用程序,其某些状态受互斥锁保护。 这是index.html

<!doctype html>
<script src=http://code.jquery.com/jquery-1.8.2.js></script>
<script src=index.js></script>

(HTML可以这么稀疏-可以看Paul Irish的演讲 )这是index.js

function request() {
    var cb = function (response) {
        console.log(response);
    };

    $.ajax({
        url: "/app",
        success: cb
    });
}

function go_slow(N, delay) {
    if (N > 0) {
        request();
        window.setTimeout(go_slow, delay, N - 1, delay);
    }
}

function go_fast(N) {
    var i;
    for (i = 0; i < N; i++) {
        request();
    }
}

window.onload = function () {
    //go_slow(100, 0);
    go_fast(100);
};

所有这些文件应放在同一目录中。 当我启动CherryPy服务器,然后访问http://localhost:8080/index.html ,控制台将显示短语“ Call#1” 100次,而CherryPy日志将显示一个对“ / app”的GET请求。 在Firefox中,我看到几个连续的控制台消息,分别显示“#1”到“#100”。 Firefox的行为符合我的预期,因为我发出了100个明确的ajax请求,并且与这些请求相关的函数每次都将返回不同的结果。

如果不是go_fast()我调用go_slow() -使用“ trampolining”(我认为这是一个变种)来强制ajax请求在不同时间从单独的函数调用中发出的变体-那么我通过“#1” Chrome和Firefox上的“#100”行为。

最后,如果我在CherryPy服务器中修改app()方法以接受一个参数,然后它会忽略该参数,就像这样(请注意, i参数不会在其他任何地方出现):

@cherrypy.expose
def app(self, i):
    with self.lock:
        self.count += 1
    return "Call #%d" % (self.count)

然后我通过更改request()go_fast()来安排go_fast()函数向"/app/" + i" (其中i是循环索引)发出ajax请求,而不只是"/app"

function request(i) {
    var cb = function (response) {
        console.log(response);
    };

    $.ajax({
        url: "/app/" + i,
        success: cb
    });
}

function go_fast(N) {
    var i;
    for (i = 0; i < N; i++) {
        request(i);
    }
}

然后我再次通过“#100”获得“#1”行为。 相反,如果我修改函数以使用例如"/app/7"作为URL(即,将上面代码段中的"/app/" + i替换为"/app/7" ),那么我会得到100次“如初始示例中所示,调用“ 1”。

在我看来,很像是某些东西 “缓存”了最初情况下实际发出的一个且唯一的ajax请求的结果(在这里我只看到“ Call#1” 100次)。 Chrome控制台中的“网络”标签仅显示了一个接收到状态代码为“ 200 OK”的ajax请求,据我所知,您必须在CherryPy中显式启用服务器端缓存。 好奇的是,在这种情况下,Firefox提供了预期的行为。

在其他情况下,由于一个或另一个原因,这种“缓存”机制被破坏了。 Trampolining可能会导致浏览器抛弃ajax请求的即时上下文,从而阻止它“记住”先前对同一URL的请求,同时将URL构造为需要位置参数,只是将每个请求赋予唯一的URL,强制发出实际请求,而不是使用任何缓存机制。

谁能具体解释这是怎么回事? 这仅仅是有关Chrome如何在短时间内处理许多Ajax请求的特性吗? 还是这种情况是拥有有状态的ajax资源的致命问题?

我认为这是一种与cache: false结合使用的竞争条件cache: false客户端的cache: false选项,请记住您的对象Root在线程池内共享。

在时间A您修改self.count ,在时间A另一个X请求(线程)返回您新修改的参数,它们是在with块上的时间A - 1with并且没有在此特定请求上返回该新计数。

当正在修改并从with语句中退出的另一个请求已经在返回中时,那么决定是否重复返回数字的原因是cherrypy线程池的处理吞吐量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM