redux传奇、WebSocket和操作队列

redux传奇、WebSocket和操作队列,websocket,redux,redux-saga,Websocket,Redux,Redux Saga,我有以下问题:服务器通过websocket向客户端发送消息。在客户端上,我需要向用户显示这些消息。但问题是,有时消息的速度很快,我需要组织一些队列,一个接一个地显示消息 我的传奇: import{eventChannel,effects,takeEvery}来自“redux saga”; 从“/actions”导入{types,actionCreators}; const{call,put,take,race}=effects; 函数监视消息(套接字){ 返回事件通道((发射器)=>{ sock

我有以下问题:服务器通过websocket向客户端发送消息。在客户端上,我需要向用户显示这些消息。但问题是,有时消息的速度很快,我需要组织一些队列,一个接一个地显示消息

我的传奇:
import{eventChannel,effects,takeEvery}来自“redux saga”;
从“/actions”导入{types,actionCreators};
const{call,put,take,race}=effects;
函数监视消息(套接字){
返回事件通道((发射器)=>{
socket.onopen=(e)=>(emitter(actionCreators.socketOpen(e));
socket.onclose=(e)=>(emitter(actionCreators.socketClose(e));
socket.onerror=(e)=>(emitter(actionCreators.socketError(e));
socket.onmessage=(e)=>(发射器(actionCreators.socketMessage(e));
return()=>{
socket.close();
};
});
}
函数*internalListener(套接字){
while(true){
const data=产量(类型.SOCKET\u SEND);
socket.send(data.payload);
}
}
函数*外部侦听器(socketChannel){
while(true){
const action=屈服带(socketChannel);
让与(行动);
}
}
函数*wsHandling(操作){
const socket=action.payload.socket;
while(true){
const socketChannel=屈服调用(watchMessages,socket);
const{cancel}=产生竞争({
任务:[调用(外部侦听器,socketChannel),调用(内部侦听器,socket)],
取消:采取(类型。插座关闭),
});
如果(取消){
socketChannel.close();
}
}
}
导出默认函数*rootSaga(操作){
屈服强度(类型:插座连接、wsHandling);
}
您可以使用
actionChannel
效果在redux saga中缓冲(排队)动作

然后,您可以以自己的速度读取通道的缓冲区

我创建了一个简化的示例,用于侦听消息并一次最多显示3条消息,每个消息持续5秒。见:


在底部,有一个控制台面板,使用它来调用
addMsg('Msg:'+Math.random())
来模拟新的socket.io消息。

所以我这样做了,下面是代码,也许它对某人有用

让pendingTasks=[];
让activeTasks=[];
函数监视消息(套接字){
返回事件通道((发射器)=>{
socket.onopen=(e)=>(emitter(actionCreators.socketOpen(e));
socket.onclose=(e)=>(emitter(actionCreators.socketClose(e));
socket.onerror=(e)=>(emitter(actionCreators.socketError(e));
socket.onmessage=(e)=>(发射器(actionCreators.socketMessage(e));
return()=>{
socket.close();
};
});
}
函数*internalListener(套接字){
while(true){
const data=产量(类型.SOCKET\u SEND);
socket.send(data.payload);
}
}
函数*外部侦听器(socketChannel){
while(true){
const action=屈服带(socketChannel);
pendingTasks=[…pendingTasks,action];
}
}
函数*wsHandling(操作){
const socket=action.payload.socket;
while(true){
const socketChannel=屈服调用(watchMessages,socket);
const{cancel}=产生竞争({
任务:[调用(外部侦听器,socketChannel),调用(内部侦听器,socket)],
取消:采取(类型。插座关闭),
});
如果(取消){
socketChannel.close();
}
}
}
函数*tasksScheduler(){
while(true){
const canDisplayTask=activeTasks.length<1&&pendingTasks.length>0;
if(canDisplayTask){
常量[firstTask,…remainingTasks]=待处理任务;
pendingTasks=剩余任务;
收益分叉(displayTask,firstTask);
屈服呼叫(延迟,300);
}
否则{
屈服呼叫(延迟,50);
}
}
}
函数*显示任务(任务){
activeTasks=[…activeTasks,task];
收益率(任务);
收益呼叫(延迟,3000);
activeTasks=\不带(activeTasks,task);
}
导出默认函数*rootSaga(操作){
屈服[
takeEvery(类型:插座连接、wsHandling),
takeEvery(类型:插座连接、任务调度程序),
];
}