通常我会使用SignalR来处理任何数据推送,但在这种情况下,我在服务器端使用Nancy Async Beta的自托管实例.我听说在这种情况下仍然可以使用SignalR,但在这种情况下,我仍然更愿意自己处理长轮询.这是我正在编写的一个简单实验应用程序的代码,它产生了下面描述的问题:
Get["/receivechat", true] = async (x, ct) =>
{
string result = await _massPublisher.WaitForResult("test");
return result;
};
Run Code Online (Sandbox Code Playgroud)
这会处理实际的长轮询请求.请求似乎以4或5的块的形式输入这个lambda.例如,如果我在lambda的第一行放置一个断点,我将看不到该断点被触发,直到我发送了4或5个请求然后突然所有请求都一次进入lambda.显然我需要他们所有人进入他们的请求所以他们都可以等待我的WaitForResult方法.WaitForResult方法只是等待一个常见的TaskCompletionSource.如有必要,我可以发布该代码和客户端代码.据我所知,这似乎是我使用Nancy Async Beta的一个问题,因为请求是并行处理的,并且请求甚至不会进入lambda,直到发出一些其他请求.
值得注意的是,此应用程序在此期间仍能响应所有其他请求.
我已经阅读了我可以在Nancy Async Beta上找到的文档,看起来这个例子应该可行......但它不是 - 对我来说无论如何.如果有人能够提供一些有关为什么不起作用的见解,那将非常感激.就像我说的那样,我可以发布更多来自这个实验的代码,但是现在它似乎只会让问题变得混乱.
更新: 由于我对TPL和Nancy相对较新,我已将我的代码从实验中删除,以便隔离问题并排除故障.这是我更新的代码.它只是等待5秒的任务延迟,然后将当前时间发送到客户端.
Get["/receivechat", true] = async (x, ct) =>
{
//string result = await _massPublisher.WaitForResult("test");
//return result;
await Task.Delay(5000);
return DateTime.Now.ToString();
};
Run Code Online (Sandbox Code Playgroud)
我的理解是每个请求将被并行处理并彼此独立.现在有了这种理解,我认为每个客户端应该每5秒看一次回复,无论有多少其他客户端轮询这些请求.但是,结果如下:

换句话说,响应每5秒发送一次,但一次只发送给一个客户端.因此,对于3个客户端,每个客户端需要15秒才能收到响应.2 = 10秒等......
到目前为止,我无法看到我做错了什么.这就是我在这里的原因.我喜欢发现我错了!:)我会学到新东西.所以,如果您知道或可能知道我哪里出错了,请告诉我.我可能已经错过了一些小而愚蠢的东西,在我多次寻找它的过程中我忽略了这一点,希望这是一个其他人会觉得有用的错误.
我正在尝试尝试Comet.我开发了一个非常简单的聊天网络应用程序 - 基本上是通过c#的彗星问候世界.我遇到的问题是IIS有时会崩溃,崩溃我的意思是它只是停止响应HTTP请求.然后,它需要重新启动应用程序池,有时甚至是整个IIS服务.我几乎肯定是罪魁祸首是我用来阻止彗星请求线程的ManualResetEvent对象,直到收到释放(更新)这些线程的信号.我尝试编写一个HTTP处理程序来解决这个问题并将可重用属性设置为false(将新请求线程放在另一个ManualResetEvent对象实例上),但这不起作用.我也在尝试实现IRegisteredObject,这样我就可以在应用程序关闭时释放那些theads,但这似乎也不起作用.它仍然崩溃,并且它崩溃时似乎没有任何模式(我已经注意到了).我几乎可以肯定它是静态实例的组合以及导致它的ManualResetEvent的使用.我只是不确定如何或如何解决这个问题.
Comet.cs(我的简单彗星lib)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Mail;
using System.Web.Hosting;
namespace Comet
{
public class CometCore : IRegisteredObject
{
#region Globals
private static CometCore m_instance = null;
private List<CometRequest> m_requests = new List<CometRequest>();
private int m_timeout = 120000; //Default - 20 minutes;
#endregion
#region Constructor(s)
public CometCore()
{
HostingEnvironment.RegisterObject(this);
}
#endregion
#region Properties
/// <summary>
/// Singleton instance of the class
/// </summary>
public static CometCore Instance
{
get
{
if (m_instance …Run Code Online (Sandbox Code Playgroud) 我遇到了处理原型方法消失(在本例中为 Array.prototype 方法)的问题,仅在 IE 中且仅当数组通过 SignalR 时。
我写了一个小/愚蠢但简单的概念验证网络应用程序来演示这个问题(代码如下)。请注意,当您单击“更新所有客户端”,然后单击“包含字母 'r' 的水果”时,_list 中的原型方法丢失导致异常。在那种情况下,数组来自 SignalR。现在,当您单击“重置”并将数组重置为硬编码值时,“包含字母 'r' 的水果”按钮突然起作用了 - 原型方法又回来了。请记住,此问题仅发生在 IE 中。
提示:当我第一次编写概念证明时,我无法重现该问题。当数组通过 SignalR 传入时,IE 仍然具有原型方法,但是在加载页面时我确实遇到了另一个错误。我不小心包含了两次 jQuery。当我取出多余的脚本以包含第二个 jQuery 时,它修复了该错误(显然),但现在可以重现该问题。然后 IE 缺少我创建的 Array 原型方法,但仅当数组通过 SignalR 出现时。
myExtensions.js:
Array.prototype.where = function (del)
{
var ret = new Array();
for (var i = 0; i < this.length; i++)
{
if (del(this[i])) ret.push(this[i]);
}
return ret;
}
Array.prototype.select = function (del)
{
var ret = new Array();
for (var i = 0; i < this.length; i++)
{
ret.push(del(this[i])); …Run Code Online (Sandbox Code Playgroud) TL'DR:有没有办法在对 API 调用使用 useEffect 时悲观地操作状态更改?
假设您编写了一个显示分页/排序数据网格的组件,并且您为该组件编写了一个 useEffect 类似于这个假示例:
useEffect(() => {
fetch(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`)
.then(response => response.json())
.then(data => setState({
data
}));
}, [paging, sorting]);Run Code Online (Sandbox Code Playgroud)
所以,如果我没记错的话,这将在分页或排序状态/道具(whatev)更新时获取。这意味着它在加载数据之前乐观地呈现新的排序和分页状态。基本上,该应用程序会告诉用户“我在请求的页面上,但我仍在加载它”。换句话说,应用程序状态的一部分(分页和排序)表示“我完成了”,状态的另一部分(加载)表示“我正在处理它”。
相比之下,如果我悲观地更新状态,我只会在获取之前将加载状态设置为 true,然后在收到响应时(并且仅在那时)设置分页、排序(& 数据和加载)。因此,该应用程序会告诉用户“我听到了您的意见,我正在处理它”,然后当收到成功响应时,该应用程序会说“这是请求的数据和更新的上下文(更新的页面/排序状态)”。
另一个问题是请求是否失败。在 optimisitic/useEffect 方法中,我现在需要恢复在尝试加载这些状态更改的数据之前更新的分页和排序状态。这种复杂性随着依赖项的数量而增加。另外,这里是关键(再次,如果我没记错的话)恢复这些状态将导致另一个获取(这可能会再次失败)。在悲观方法中,您只需在发生错误时设置 loading = false 并且不会进行其他状态更改,因为分页和排序仅在成功接收数据时更新。数据以悲观的方式(不乐观)保持同步,这就是为什么我认为当博客和视频在使用 useEffect 时说“从同步的角度思考”是具有讽刺意味的。
还有一件事,比如说从 useEffect 内部调用的 API(在其他一些例子中)实际上正在改变服务器端的某些东西。在这种情况下,当使用 useEffect 并应用它的乐观方法时,只会对用户撒谎。该应用程序说“好的,我更新了”。也许不吧。如果没有(如果有错误),希望有状态更新来恢复对用户撒谎的状态更改,并在恢复该状态时以某种方式避免额外的 API 调用。希望用户看到状态变回并希望有一条消息......即便如此,这是一个好的用户体验吗?
我并不是说乐观渲染总是不好的。我的意思是“我大部分时间都喜欢悲观。我如何在使用 useEffect 时做到这一点?” :)
似乎 useEffect 正在被用于和推广应用程序的大多数副作用(很多)。我并不经常发现它很有用。我是一个悲观主义者,希望获得替代方案。
c# ×2
.net ×1
async-await ×1
comet ×1
iis ×1
long-polling ×1
nancy ×1
prototype ×1
react-hooks ×1
reactjs ×1
signalr ×1
use-effect ×1