SocketIO 限制进度观看请求
SocketIO limit requests on progress watching
我正在将 SocketIO 用于一个小型应用程序,只要发生更改,用户就会收到更新。但是,我想实现它以在服务器端完成的任务中实现实时进度可视化。
但是,如果任务进度变化太快,这将导致大量事件排放,我认为这可能会降低应用程序性能。有没有办法将事件发射限制为每秒最多 N 次(仅发射最后一个,进度的最后一个百分比)?
是的,可以做到。它要求您将事件保持一小段时间,以查看是否有更多同类事件到来,从而将所有事件合并为一个。我将在几分钟内编写一个示例。
以下是您如何执行此操作的一般思路:
function emitMessageLast(socket, msg, data) {
const queueTime = 500; // wait for up to 500ms of idle time before sending latest data
const longestWaitTime = 2000; // wait no more than 2 seconds if data is being continuously sent
function stopTimer() {
if (socket._timer) {
clearTimeout(socket._timer);
socket._timer = null;
}
}
function sendNow() {
socket._lastMsg = msg;
socket._lastTime = Date.now();
return socket.emit(msg, data);
}
// if this is the first time we're sending this message
// or it's been awhile since we last sent data
// just send the new data immediately
if (socket._lastMsg !== msg || !socket._lastTime || Date.now() - socket._lastTime > longestWaitTime) {
stopTimer();
return sendNow();
}
// at this point, we know we're sending the same message as has recently been sent
socket._lastMsg = msg;
socket._lastData = data;
stopTimer();
// set a timer so that if no more data has arrived before the timer fires,
// we sent the last data we saved
socket._timer = setTimeout(() => {
socket._timer = null;
sendNow();
}, queueTime);
}
这段代码的大致思路如下:
- 当您接到要发送的消息而最近没有发送过相同类型的消息时,请立即发送这条消息并记录发送时间。
- 当您接到要发送消息的电话并且距离上次发送消息已经超过
longestWaitTime
时,请立即发送这条消息。这意味着如果服务器持续发送数据,服务器将等待最多 longestWaitTime
,然后再发送最新的数据值。
- 当服务器偶尔发送数据时,它会等待
queueTime
(等待查看是否有更多数据到来),然后才发送最后一条数据。它实质上是在缓冲最后一条消息,直到在最后 queueTime
中没有发送更多消息,然后计时器将触发最后一条消息。
- 我在这里配置了默认值,这样它会延迟向客户端发送数据最多 500 毫秒(同时等待查看服务器是否即将发送更多数据,这样它就可以避免发送所有中间值数据)计算出如果客户端每 500 毫秒更新一次它的状态,那已经足够频繁了。而且,如果服务器持续发送更新,那么服务器将跳过最多 2000 毫秒的更新,只发送最后一次更新。同样,您可以根据自己的喜好设置这些数字。
我正在将 SocketIO 用于一个小型应用程序,只要发生更改,用户就会收到更新。但是,我想实现它以在服务器端完成的任务中实现实时进度可视化。
但是,如果任务进度变化太快,这将导致大量事件排放,我认为这可能会降低应用程序性能。有没有办法将事件发射限制为每秒最多 N 次(仅发射最后一个,进度的最后一个百分比)?
是的,可以做到。它要求您将事件保持一小段时间,以查看是否有更多同类事件到来,从而将所有事件合并为一个。我将在几分钟内编写一个示例。
以下是您如何执行此操作的一般思路:
function emitMessageLast(socket, msg, data) {
const queueTime = 500; // wait for up to 500ms of idle time before sending latest data
const longestWaitTime = 2000; // wait no more than 2 seconds if data is being continuously sent
function stopTimer() {
if (socket._timer) {
clearTimeout(socket._timer);
socket._timer = null;
}
}
function sendNow() {
socket._lastMsg = msg;
socket._lastTime = Date.now();
return socket.emit(msg, data);
}
// if this is the first time we're sending this message
// or it's been awhile since we last sent data
// just send the new data immediately
if (socket._lastMsg !== msg || !socket._lastTime || Date.now() - socket._lastTime > longestWaitTime) {
stopTimer();
return sendNow();
}
// at this point, we know we're sending the same message as has recently been sent
socket._lastMsg = msg;
socket._lastData = data;
stopTimer();
// set a timer so that if no more data has arrived before the timer fires,
// we sent the last data we saved
socket._timer = setTimeout(() => {
socket._timer = null;
sendNow();
}, queueTime);
}
这段代码的大致思路如下:
- 当您接到要发送的消息而最近没有发送过相同类型的消息时,请立即发送这条消息并记录发送时间。
- 当您接到要发送消息的电话并且距离上次发送消息已经超过
longestWaitTime
时,请立即发送这条消息。这意味着如果服务器持续发送数据,服务器将等待最多longestWaitTime
,然后再发送最新的数据值。 - 当服务器偶尔发送数据时,它会等待
queueTime
(等待查看是否有更多数据到来),然后才发送最后一条数据。它实质上是在缓冲最后一条消息,直到在最后queueTime
中没有发送更多消息,然后计时器将触发最后一条消息。 - 我在这里配置了默认值,这样它会延迟向客户端发送数据最多 500 毫秒(同时等待查看服务器是否即将发送更多数据,这样它就可以避免发送所有中间值数据)计算出如果客户端每 500 毫秒更新一次它的状态,那已经足够频繁了。而且,如果服务器持续发送更新,那么服务器将跳过最多 2000 毫秒的更新,只发送最后一次更新。同样,您可以根据自己的喜好设置这些数字。