这些API是否与服务器发送事件对称,以生成从浏览器到服务器的“即发即弃”事件?我知道如何不回复服务器端的请求,但如何告诉浏览器它不需要等待回复?
这里的目标是在客户端节省资源,比如你想尽快向服务器发送10k事件,而不是关心服务器回复的内容。
编辑虽然这个问题大多与此无关,但这里有一些关于我正在开发的项目的背景知识,它将使用“AJAX即发即忘”。我想为Scala.js构建一个JavaScript网络库,它将其应用程序作为JVM上的Akka actor和浏览器(使用Scala.js编译)之间的传输层。当WebSockets不可用时,我希望有一些回退,并且在每个JS-> JVM消息的往返期间都有一个挂起的连接是不可接受的。
答案 0 :(得分:4)
正如您要求"如何告诉浏览器它不需要等待回复?" 我假设您不想处理服务器回复。
在这种情况下,最好利用Google实施的一种像素图像响应技巧进行分析和跟踪,以及许多其他此类服务。
诀窍是使用javascript创建新图像并设置src属性,浏览器将立即触发图像请求,浏览器可以并行请求多个此类请求。
var image = new Image();
image.src = "your-script.php?id=123&other_params=also";
优点: 易于实施 减少服务器/客户端的负载,然后是ajax请求
缺点: 您只能使用此appproach发送GET请求。
修改强>
更多参考资料:
http://help.yahoo.com/l/us/yahoo/ywa/faqs/tracking/advtrack/3520294.html
https://support.google.com/dfp_premium/answer/1347585?hl=en
How to create and implement a pixel tracking code
他们再次使用相同的像素图像技术。
答案 1 :(得分:3)
所以,为了清楚起见,您正在尝试使用XMLHttpRequest作为网络通信的代理,这意味着您完全可以使用XMLHttpRequest提供的任何内容,对吗?
我的看法是,如果您为此坚持使用XMLHttpRequest,那么您将不得不通过获得服务器响应来实现和平。只是异步调用并通过no-op函数处理响应。考虑一下其他人的建议,使用服务器上的队列(或服务器上的异步方法),以便立即返回客户端。否则,我真的认为JavaScript只是你正在描述的工作的错误工具。
XMLHttpRequest将成为每个浏览器中不同的实现(提供或多或少的通用接口契约)。我的意思是,微软发明了这个东西,然后其他浏览器制造商模仿它,然后瞧,每个人都开始称它为Web 2.0。重点是,如果你在XMLHttpRequest的繁琐中心过于刻板,你可能会在不同的浏览器中获得不同的行为。
据我所知,XMLHttpRequest严格使用TCP(没有UDP选项),所以至少你的客户端将从服务器接收TCP ACK。没有办法告诉服务器不要在该级别做出响应。它已经融入了TCP / IP网络堆栈。
此外,通信使用HTTP协议,因此服务器将使用HTTP标头进行响应......对吗?我的意思是,这就是协议定义的方式。将HTTP视为不同的东西有点像告诉猫像鸡一样吠叫。
即使您可以通过在XMLHttpRequest上调用abort()来取消客户端上的请求,您也不会在服务器端取消它。为此,即使可以使用XMLHttpRequest,也需要向服务器发送一个额外的请求,告诉它取消对前一个请求的响应。它如何知道取消哪个响应?您必须管理某种类型的请求ID。您必须能够适应无序取消请求。复杂。
所以这里有一个想法(我只是大声思考):微软的XMLHttpRequest至少在精神上基于Visual Interdev时代的早期微软技术,它使用Java客户端上的applet以异步方式向服务器发出请求,然后在响应出现时将控制传递给首选的JavaScript回调函数等。非常熟悉。
在整个Sun与微软诉讼惨败期间,Java异步请求事件得到了解决。我听说有传言说,任何时候,当他了解到使用Java实现微软技术并杀死技术时,某个原始的微软首席执行官会吹响垫片。谁知道?当这种能力消失了几年之后我很不高兴,然后当XMLHttpRequest最终出现时再次开心。
也许你看到我要去的地方,这里......: - )
我想也许您正在尝试从XMLHttpRequest中挤出行为,它只是没有为它构建。
答案可能是编写自己的Java小程序,进行一些套接字编程,并让它进行您希望从中看到的那种通信。但是,当然,您在浏览器中没有启用Java的人会遇到问题,最近的Java安全问题会加剧这种问题。所以你要查看代码签名证书等等。而且您还在查看您需要在服务器端解决的问题。如果仍然使用HTTP并通过Web服务器工作,Web服务器仍然希望发送HTTP响应,这仍将占用服务器上的资源。您可以在服务器上进行异步操作,这样TCP套接字就不会超过必要的时间,但您仍然需要在服务器端占用资源。
答案 2 :(得分:1)
我设法使用2ms的非常小的超时来获得预期的行为。服务器可以看到以下调用,但在来自服务器的任何回复之前,客户端上的连接已关闭:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 2) {
alert("Response header recived, it was not a fire-and-forget...");
}
};
xhr.open("POST", "http://www.service.org/myService.svc/Method", true);
xhr.timeout = 2;
xhr.send(null);
这并不完全令人满意,因为浏览器/计算机之间的超时可能会发生变化(例如,1ms在我的设置中不起作用)。使用大小为50ms的超时意味着客户端可能达到最大并发打开连接的限制(我的设置为6)。
答案 3 :(得分:0)
使用XMLHttpRequest发送异步请求(即,您不关心它是否成功或响应是什么:
var req = new XMLHttpRequest();
req.open('GET', 'http://my.url.goes.here.com');
req.send();
你也可以用Image对象做同样的事情,btw:
new Image().src = 'http://my.url.goes.here.com';
如果您正在进行跨域请求,则Image方法特别有效,因为Image不受XHR请求方式的同源安全限制。 (顺便说一句,这是一个很好的做法,但不是必不可少的,让你的端点返回一个1x1像素的PNG或GIF响应与适当的内容类型,以避免浏览器控制台警告,如'资源解释为图像,但转移MIME类型text / html'。)
答案 4 :(得分:0)
听起来你正试图解决错误的问题。而不是在客户端处理这个,为什么不在服务器端处理这个。
从客户端获取消息并在服务总线上发送消息或将数据存储在数据库中并返回到客户端。根据您的堆栈和体系结构,这应该非常简单且非常快。您可以在带外处理消息,或者第二个服务侦听消息总线并处理请求,或者某种批处理器可以在以后出现并处理数据库中的记录。
答案 5 :(得分:0)
对于与XHR的连接,您将不会像使用WebSockets那样进行相同级别的细粒度控制。最终,它是管理HTTP连接生命周期的浏览器。
您可以存储和批处理事件,而不是从WebSockets回退到离散的XHR连接。例如:
客户端JS
function sendMessage(message) {
WebSocketsAvailable ? sendWithWebSockets(message) : sendWithXHR(message);
}
var xhrQueue = [];
function sendWithXHR(message) {
xhrQueue.push({
timestamp: Date.now(), // if this matters
message: message
});
}
function flushXhrQueue() {
if (xhrQueue.length) {
var req = new XMLHttpRequest();
req.open('POST', 'http://...');
req.onload = function() { setTimeout(flushXhrQueue, 5000); };
// todo: needs to handle errors, too
req.send(JSON.stringify(xhrQueue));
xhrQueue = [];
}
else {
setTimeout(flushXhrQueue, 5000);
}
}
setTimeout(flushXhrQueue, 5000);
在服务器上,也许你可以有两个端点:一个用于WebSockets,另一个用于XHR。 XHR处理程序反序列化JSON队列对象,并调用(每个消息一次)WebSockets处理程序使用的相同处理程序。
服务器伪代码
function WSHandler(message) {
handleMessage(message, Date.now());
}
function XHRHandler(jsonString) {
var messages = JSON.parse(jsonString);
for (var messageObj in messages) {
handleMessage(messageObj.message, messageObj.timestamp);
}
}
function handleMessage(message, timestamp) {
...
}