多个ajax请求到同一URL的奇怪行为

时间:2013-09-29 23:05:07

标签: javascript ajax browser browser-cache cherrypy

我在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可以很稀疏 - 请参阅this talk from 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请求在不同时间从单独的函数调用发出 - 然后我在Chrome和Firefox上获得“#1”到“#100”行为。

最后,如果我修改CherryPy服务器中的app()方法接受一个然后忽略的参数,就像这样(注意其他地方没有出现的i参数):

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

我安排go_fast()函数通过更改{{"/app/" + i"i(其中"/app"是循环索引)而不仅仅request()发出ajax请求1}}和go_fast()是这样的:

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控制台中的“网络”选项卡只显示一个ajax请求,其状态代码为“200 OK”,据我所知,您必须在CherryPy中明确启用服务器端缓存。在这种情况下,Firefox也会产生预期行为的好奇心。

在其他情况下,由于某种原因,这种“缓存”机制被打败了。 Trampolining可能会导致浏览器抛出ajax请求的直接上下文,阻止它“记住”先前对同一URL的请求,同时设想URL需要位置参数只是给每个请求一个唯一的URL,强制实际请求结束,而不是使用任何缓存机制。

任何人都可以具体解释这里发生了什么吗?关于Chrome如何在短时间内处理许多ajax请求,这仅仅是一个特点吗?或者这种情况是否具有有状态的ajax资源是一个致命的问题?

1 个答案:

答案 0 :(得分:0)

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

按时A您修改self.count并按时A另外X个请求(线程)正在返回A - 1 with上新修改的参数{{1}} {{1}} 1}}阻止并且没有在此特定请求上返回该新计数。

当正在修改和退出with语句的请求已经在返回时,那么确定返回的数字的重复或不存在的是cherrypy的线程池的处理吞吐量。