在我当前的项目中,我正在处理 Firebase Websocket 订阅。不同的组件可以订阅不同的数据,例如在项目列表中,每个 ListItem
组件通过在 componentDidMount
中分派(dispatch) SUBSCRIBE
操作来订阅该特定项目的 websocket“事件”,并取消订阅在 componentWillUnmount
中调度 UNSUBSCRIBE
操作。
我的传奇是这样的:
const subscriptions = {}
export function * subscribeLoop () {
while (true) {
const { path } = yield take(SUBSCRIBE)
subscriptions[path] = yield fork(subscription, path)
}
}
export function * unsubscribeLoop () {
while (true) {
const { path } = yield take(UNSUBSCRIBE)
yield cancel(subscriptions[path])
}
}
export function * subscription (path) {
let ref
try {
const updateChannel = channel()
ref = api.child(path)
ref.on('value', snapshot => {
updateChannel.put(snapshot.val())
})
while (true) {
const data = yield take(updateChannel)
yield put(handleUpdate(path, data))
}
} finally {
if (yield cancelled()) {
ref.off()
ref = null
}
}
}
我认为这不是处理这个问题的正确方法 - 对于 500 个项目的列表来说,它确实相当慢。
如何优化性能?
- 我还需要 fork 吗?
- 我应该引入某种延迟来给线程一些空间来处理其他事情吗?
任何提示表示赞赏。
最佳答案
Should i introduce some kind of delay to give the thread some space > to handle other things?
首先,有必要记住,使用 redux saga 和 fork 等效果实际上不会创建任何会在无限循环中扭曲的线程。它只是用于组织回调链的语法糖,因为yield 运算符在两侧提供对象传递。从这个 Angular 来看,强制延迟的问题没有意义——因为线程并不存在。
Do i even need to fork?
如果具备适当的技能,通常可以在没有一组调用 fork 的情况下完成任务,并在一个根传奇中完成所有操作。这个想法是在 websocket 上的当前词法区域中使用回调函数进行订阅,并期望在延迟 promise 的基础上在伪无限循环中获取消息。
从概念上讲,代码大致如下:
const subscribers = new Map()
function * webSocketLoop() {
let resolver = null
let promise = new Promise(resolve => (resolver = resolve))
let message = null;
websocket.on('message', (payload) => {
message = Object.assign({}, payload)
resolver()
promise = promise.then(() => new Promise(resolve => (resolver = resolve)))
})
while(true) {
yield call(() => promise)
const type = message.type
const handlers = subscribers.get(type) || []
handlers.forEach(func => func(message))
}
}
export function * mainSaga () {
yield takeEvery(SUBSCRIBE, subscribe)
yield takeEvery(UNSUBSCRIBE, unsubscribe)
yield fork(webSocketLoop)
}
关于javascript - 使用 redux-saga 处理大量事件的订阅/取消订阅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43603913/