我正在构建RESTful服务器,并为此编写一个javascript客户端。客户端的首页显示了数据库中数据的一些统计信息。特别是:我有一个6×3的表,其中的每个单元格均以'...'文本初始化,并具有一个query
数据字段。在document.ready(客户端)上,我调用以下代码:
$('#home-page table td').map(function (i, x) {
$.getJSON("/url/count?q=" + $(x).data('query'),
function(data){
$(x).text(data['__total__'])
});
})
及其作用是,它在18个表单元中的每个单元上执行内部未命名函数,将对应的查询发送到我的服务器,并注册一个同样未命名的回调以处理结果。服务器执行数据库查询,然后计算结果中的项目,然后返回一个元素的字典。
现在有趣的是,Firefox将保留第7个请求,等待前6个请求之一处理。我曾以为是服务器中的内容,但是感谢this question和this page,我可以确认它在我的Web浏览器中是一个限制。
Splitting my server over three or four ports听起来很糟糕。
也要调整设置,我不想让每个用户都这样做。
相比于默认的6限制,此图显示了如果我可以同时放置18个GET请求的响应时间。红色是blocked
时间。
或者我放弃,并且一次全部更新表,但是我喜欢单元格一个接一个地更新的效果,这至少要花费所有请求最多的时间。
或者我可以对单元格进行排序,以便最有可能首先请求最快的单元格(三列第一行中的6个单元格显示select count(*) from table_i
的结果)。接下来的两列仍然会有相同的问题。
那么我该如何解决这个问题,否则通常会满足要求:所有请求都在同一时间提出;每个结果准备就绪后都会收到。
我有一个主意,我将其详细解释为一个答案,但我不知道你们会做什么。
这是问题的开头文字,直到我找到问题的真正根源。
这是从日志中看的样子:
$ mix phx.server
Generated luke app
[info] Running LukeWeb.Endpoint with Cowboy using http://0.0.0.0:4000
15:00:56 - info: compiled 6 files into 2 files, copied 3 in 2.8 sec
[info] GET /
[info] Sent 200 in 56ms
[info] GET /url/count
[info] GET /url/count
[info] GET /url/count
[info] GET /url/count
[info] GET /url/count
[info] GET /url/count
[info] Sent 200 in 678ms
[info] GET /url/count
[info] Sent 200 in 1675ms
[info] GET /url/count
[info] Sent 200 in 2859ms
[info] GET /url/count
[info] Sent 200 in 1895ms
[info] GET /url/count
[info] Sent 200 in 3956ms
[info] Sent 200 in 3963ms
[info] GET /url/count
[info] GET /url/count
[info] Sent 200 in 657ms
[info] GET /url/count
[info] Sent 200 in 4801ms
[info] GET /url/count
[info] Sent 200 in 1196ms
[info] GET /url/count
[info] Sent 200 in 1511ms
[info] GET /url/count
[info] Sent 200 in 4882ms
[info] GET /url/count
[info] Sent 200 in 2950ms
[info] GET /url/count
[info] Sent 200 in 1306ms
[info] Sent 200 in 1099ms
[info] Sent 200 in 1880ms
[info] Sent 200 in 2349ms
[info] Sent 200 in 4885ms
[info] Sent 200 in 3558ms
服务器端,最相关的代码是这样的(我还没有实现任何东西,这只是一个随机的睡眠时间):
defmodule LukeWeb.CountController do
use LukeWeb, :controller
def index(conn, _params) do
sleeping = :crypto.rand_uniform(500, 5000)
:timer.sleep(sleeping)
result = %{"__total__" => sleeping}
json conn, result
end
end
还有router.ex
的各个部分:
defmodule LukeWeb.Router do
use LukeWeb, :router
pipeline :api do
plug :accepts, ["json"]
end
scope "/url", LukeWeb do
pipe_through :api
get "/count", CountController, :index
end
end
答案 0 :(得分:0)
我的想法基于令牌和递归。我将所有请求作为一个查询数组一次放置,然后我会立即收到一个令牌,用于标识请求集。
然后,cash_token
函数将令牌提供给服务器,并使用以下结构注册用于处理它的回调:
function cash_token(token, args) {
var itr, itd, ispan, btn;
$.getJSON("/browse/cash-token/{}".format(token), function(data) {
.
.
.
if (not_yet_done) {
setTimeout(partial(cash_token, token, args), 1);
}
})}
这些仅是客户端方面的准则,显然我还没有编写最终代码,而服务器端,我需要了解更多Elixir
。