- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 redux-saga 从我的 react App 连接到 websocket 服务器,并希望捕获连接丢失(服务器错误,重新启动)以便以 4 秒的间隔重新连接,直到连接再次恢复。问题是在重新连接到 webSocket 时 redux store 不再更新。
我尝试按照以下代码使用 redux-saga 的 eventChannel。不幸的是,没有或者至少我找不到任何文档来回答 ws reconnect in redux-saga。
import {eventChannel} from 'redux-saga';
import {all, takeEvery, put, call, take, fork} from 'redux-saga/effects'
import {INITIALIZE_WS_CHANNEL} from "../../constants/ActionTypes"
import {updateMarketData} from "../actions"
function createEventChannel() {
return eventChannel(emit => {
//Subscribe to websocket
const ws = new WebSocket('ws://localhost:9000/rates');
ws.onopen = () => {
console.log("Opening Websocket");
};
ws.onerror = error => {
console.log("ERROR: ", error);
};
ws.onmessage = e => {
return emit({data: JSON.parse(e.data)})
};
ws.onclose = e => {
if (e.code === 1005) {
console.log("WebSocket: closed");
} else {
console.log('Socket is closed Unexpectedly. Reconnect will be attempted in 4 second.', e.reason);
setTimeout(() => {
createEventChannel();
}, 4000);
}
};
return () => {
console.log("Closing Websocket");
ws.close();
};
});
}
function * initializeWebSocketsChannel() {
const channel = yield call(createEventChannel);
while (true) {
const {data} = yield take(channel);
yield put(updateMarketData(data));
}
}
export function * initWebSocket() {
yield takeEvery(INITIALIZE_WS_CHANNEL, initializeWebSocketsChannel);
}
export default function* rootSaga() {
yield all ([
fork(initWebSocket)
]);
}
更新
为了完成@azundo 为寻找 websocket 和 redux-saga 完整示例的人所接受的答案,我添加了以下代码:
function * initializeWebSocketsChannel() {
console.log("going to connect to WS")
const channel = yield call(createEventChannel);
while (true) {
const {data} = yield take(channel);
yield put(updateMarketData(data));
}
}
export function * startStopChannel() {
while (true) {
yield take(START_CHANNEL);
yield race({
task: call(initializeWebSocketsChannel),
cancel: take(STOP_CHANNEL),
});
//if cancel wins the race we can close socket
ws.close();
}
}
export default function* rootSaga() {
yield all ([
startStopChannel()
]);
}
START_CHANNEL 和 STOP_CHANNEL 操作可以在 componentDidMount 和 componentWillUnmount 分别是 React 组件生命周期。
最佳答案
这不起作用的原因是因为您对 createEventChannel
的递归调用没有被 yield
ed 到 saga 中间件 redux-saga
无法知道后续事件 channel 的创建。您会希望在事件 channel 中定义递归函数,请参阅下面的代码,因此只有一个 eventChannel
始终挂接到商店中。
另请注意,在预期的套接字关闭时添加了发射 END,这样您就不会在不重新连接时让 eventChannel 永远打开。
import {eventChannel, END} from 'redux-saga';
let ws; //define it here so it's available in return function
function createEventChannel() {
return eventChannel(emit => {
function createWs() {
//Subscribe to websocket
ws = new WebSocket('ws://localhost:9000/rates');
ws.onopen = () => {
console.log("Opening Websocket");
};
ws.onerror = error => {
console.log("ERROR: ", error);
};
ws.onmessage = e => {
return emit({data: JSON.parse(e.data)})
};
ws.onclose = e => {
if (e.code === 1005) {
console.log("WebSocket: closed");
// you probably want to end the channel in this case
emit(END);
} else {
console.log('Socket is closed Unexpectedly. Reconnect will be attempted in 4 second.', e.reason);
setTimeout(() => {
createWs();
}, 4000);
}
};
}
createWs();
return () => {
console.log("Closing Websocket");
ws.close();
};
});
}
关于reactjs - 在 redux-Saga 中重新连接到 webSocket 服务器的标准方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58026629/
有什么方法可以将来自 node_modules 的 sagas 与我为我的应用程序编写的其他 sagas 结合起来吗?如果 sagaMiddleware.run() 接受 sagas 数组,但 id
我熟悉redux-thunk,今天来redux-saga,我知道当我们要处理异步的时候,redux-saga需要先调用一个actions作为signal,然后sagas来处理,返回成功/失败操作,所以
如果我有两个 sagas 在同一 Action 上等待 yield take(),是否可以保证哪个 saga 将首先选择该 Action 并执行其剩余逻辑或者是随机的?我需要确保第一个传奇在第二个传奇
我一直在关注 AxonBank example为了理解 Axon 框架中 Saga 的实现,并有一些像这样的代码来开始和结束 saga @Saga public class MoneyTransfer
我有一个基本的传奇,如下所示: const mySaga = function* () { yield takeEvery("SOME_ACTION_REQUEST", function* (
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我正在开发一个使用 redux-saga 的项目管理来自 API 调用的状态更改。 我看过很多关于如何对传奇进行单元测试的例子,但很少有例子可以用来实际进行集成测试。我们正在使用 jest对于断言。
我有下一个代码: const sagaMiddleware = createSagaMiddleware(options); . . . const createdStore = createStor
当调度一个 Action 时,它到达 reducer 和传奇的顺序是否得到保证? 我可以信赖它 首先进入reducer 那么传奇呢? reducer : function reducer(state
我们的应用程序使用尝试 - 成功 - 失败的方法来处理来自服务器的响应。 我有一个生成器函数,需要像这样运行: function * getSingleSectorAttempt(action) {
当它在屏幕上可见时,我正在记录横幅展示次数。 当用户滚动时,同一条横幅可以在短时间内多次显示。 我想防止这种情况发生。 乍一看,throttle是防止它的完美方法。 但是,当您在一页中有多个横幅时,t
我在 containers/App/sagas.js 中有一个 sagas.js,它包含一个登录 saga,我试图从一个登录弹出窗口调用它,它也有自己的 sagas.js (components/Lo
我有一个 Saga,我需要在其中执行 3 个异步请求,然后在后续请求中使用这 3 个请求的响应。这里有一些伪代码来解释: function* useOtherActionsAndSagas(actio
所以,我是 react 样板的新手,似乎没有办法在不影响前一个传奇的功能的情况下包含另一个传奇(即它不起作用)。 我尝试将 sagas 声明为常量,然后将其传递到容器末尾的 compose 函数中,但
我有以下情况: export function* addCircle(circleApi, { payload }) { try { const response = yiel
以前也有人问过类似的问题,但答案对我没有任何帮助。 What are selectors in redux? How to get something from the state / store i
我有一个运行良好的传奇,我调用一个操作并包含一些数据,传奇被触发,它从操作中提取值,执行API调用并以几个yield put结束 - 太棒了。 我现在正在尝试测试该传奇并解决问题,我已经编写了一个简单
我使用 redux-saga 的主要原因之一是它进行异步函数调用的可测试性。我的困境是,当我使用不属于我的 redux 存储的有状态对象进行编程时,使用 sagas 进行编程变得非常尴尬。是否有使用非
我是传奇世界的新手。虽然我在 react-native 领域使用过 thunk,但此刻我很困惑。我正在努力让我的项目的骨架继续运行,我希望它很快就会变得非常大。考虑到这一点,我试图将逻辑分成多个文件。
我正在使用 saga eventChannel 来监听正在触发的事件(可能是实际应用程序中的 WebSocket),然后我正在更新我的 Redux Store。在组件中,我正在调用 API 操作。然后
我是一名优秀的程序员,十分优秀!