我看到代码有奇怪的行为 here .
客户端(Javascript):
<input type="text" id="userid" placeholder="UserID" /><br />
<input type="button" id="ping" value="Ping" />
<script>
var es = new EventSource('/home/message');
es.onmessage = function (e) {
console.log(e.data);
};
es.onerror = function () {
console.log(arguments);
};
$(function () {
$('#ping').on('click', function () {
$.post('/home/ping', {
UserID: parseInt($('#userid').val()) || 0
});
});
});
</script>
服务器端(C#):
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Web.Mvc;
using Newtonsoft.Json;
namespace EventSourceTest2.Controllers {
public class PingData {
public int UserID { get; set; }
public DateTime Date { get; set; } = DateTime.Now;
}
public class HomeController : Controller {
public ActionResult Index() {
return View();
}
static ConcurrentQueue<PingData> pings = new ConcurrentQueue<PingData>();
public void Ping(int userID) {
pings.Enqueue(new PingData { UserID = userID });
}
public void Message() {
Response.ContentType = "text/event-stream";
do {
PingData nextPing;
if (pings.TryDequeue(out nextPing)) {
var msg = "data:" + JsonConvert.SerializeObject(nextPing, Formatting.None) + "\n\n";
Response.Write(msg);
}
Response.Flush();
Thread.Sleep(1000);
} while (true);
}
}
}
一旦我按下 ping 将新项目添加到 pings 队列中,Message 方法内的循环就会选择新项目并发出一个事件,通过Response.Write(在服务器上使用 Debug.Print 确认)。但是,浏览器不会触发 onmessage 直到我第二次按下 ping,并且浏览器发出另一个事件;此时来自 first 事件的数据到达 onmessage。
我该如何解决这个问题?
澄清一下,这是我期望的行为:
Client Server
-------------------------------------------------------------------
Press Ping button
XHR to /home/ping
Eneque new item to pings
Message loop issues server-sent event
EventSource calls onmessage
这是实际发生的事情:
Client Server
-------------------------------------------------------------------
Press Ping button
XHR to /home/ping
Eneque new item to pings
Message loop issues server-sent event
(Nothing happens)
Press Ping button again
New XHR to /home/ping
EventSource calls onmessage with previous event data
(在 Chrome 中运行时,message 请求在“网络”选项卡中列为始终未决。我不确定这是服务器发送事件的正常行为,还是与问题。)
编辑
Response.Write 之后的 msg 变量的字符串表示形式如下所示:
"data:{\"UserID\":105,\"Date\":\"2016-03-11T04:20:24.1854996+02:00\"}\n\n"
非常清楚地包括换行符。
最佳答案
这不是一个答案,但希望它会成为一个答案。我能够使用以下代码让它工作。
public void Ping(int id)
{
pings.Enqueue(new PingData { ID = id });
Response.ContentType = "text/plain";
Response.Write("id received");
}
public void Message()
{
int count = 0;
Response.ContentType = "text/event-stream";
do {
PingData nextPing;
if (pings.TryDequeue(out nextPing)) {
Response.ClearContent();
Response.Write("data:" + nextPing.ID.ToString() + " - " + nextPing.Date.ToLongTimeString() + "\n\n");
Response.Write("event:time" + "\n" + "data:" + DateTime.Now.ToLongTimeString() + "\n\n");
count = 0;
Response.Flush();
}
if (!Response.IsClientConnected){break;}
Thread.Sleep(1000);
count++;
} while (count < 30); //end after 30 seconds of no pings
}
造成差异的代码行是第二个 Response.Write。在下一次与您的问题类似的 ping 之前,该消息不会出现在浏览器中,但 ping 始终会出现。如果没有该行,ping 只会在下一次 ping 之后出现,或者在我的 30 秒计数器用完后出现。
在 30 秒计时器后出现的丢失消息让我得出结论,这要么是 .Net 问题,要么是我们遗漏了什么。这似乎不是事件源问题,因为该消息出现在服务器事件上,而且我在使用 PHP 执行 SSE 时没有遇到任何问题。
作为引用,这是我用来测试的 JavaScript 和 HTML。
<input type="text" id="pingid" placeholder="ID" /><br />
<input type="button" id="ping" value="Ping" />
<div id="timeresponse"></div>
<div id="pingresponse"></div>
<script>
var es = new EventSource('/Home/Message');
es.onmessage = function (e) {
console.log(e.data);
document.getElementById('pingresponse').innerHTML += e.data + " - onmessage<br/>";
};
es.addEventListener("ping", function (e) {
console.log(e.data);
document.getElementById('pingresponse').innerHTML += e.data + " - onping<br/>";
}, false);
es.addEventListener("time", function (e) {
document.getElementById('timeresponse').innerHTML = e.data;
}, false);
es.onerror = function () {
console.log(arguments);
console.log("event source closed");
es.close();
};
window.onload = function(){
document.getElementById('ping').onclick = function () {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onload = function () {
console.log(this.responseText);
};
var url = '/Home/Ping?id=' + document.getElementById('pingid').value;
xmlhttp.open("GET", url);
xmlhttp.send();
};
};
</script>
关于javascript - 客户端总是响应之前服务器发送的事件,而不是当前事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35719486/
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候