我在 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 请求的变体 - 那么我通过“#100”行为得到“#1” Chrome 和 Firefox。
最后,如果我修改app()
CherryPy 服务器中的方法以接受它然后忽略的参数,就像这样(注意i
没有出现在其他任何地方的参数):
@cherrypy.expose
def app(self, i):
with self.lock:
self.count += 1
return "Call #%d" % (self.count)
我安排go_fast()
函数向"/app/" + i"
(i
循环索引在哪里)发出ajax请求,而不是"/app"
通过改变request()
和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 次重复的“Call #1”,如初始示例中所示。
对我来说,它看起来很像某些东西“缓存”了在初始情况下实际发出的唯一一个 ajax 请求的结果(我只看到了“Call #1”100 次)。Chrome 控制台中的“网络”选项卡仅显示接收状态代码“200 OK”的一个 ajax 请求,据我所知,您必须在 CherryPy 中显式启用服务器端缓存。Firefox 在这种情况下给出了预期的行为也令人好奇。
在其他情况下,由于某种原因,这种“缓存”机制被打败了。Trampolining 可能会导致浏览器丢弃 ajax 请求的直接上下文,从而阻止它“记住”先前对同一 URL 的请求,同时设计 URL 要求位置参数只是为每个请求提供一个唯一的 URL,强制发出实际请求,而不是使用任何缓存机制。
谁能具体解释这里发生了什么?这仅仅是关于 Chrome 如何在短时间内处理许多 ajax 请求的一个特点吗?或者这种情况是拥有有状态 ajax 资源的致命问题吗?