在我目前的项目中,我正在处理firebase websocket订阅。不同的组件可以订阅不同的数据,例如在项目列表中,每个ListItem
组件通过在SUBSCRIBE
中分派componentDidMount
操作订阅该特定项目的websocket“事件”,并通过调度UNSUBSCRIBE
操作取消订阅componentWillUnmount
。
我的传奇看起来像这样:
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件物品清单上确实相当慢。
如何优化效果?
任何提示都表示赞赏。
答案 0 :(得分:1)
我应该引入某种延迟来给线程一些空间>处理其他事情?
首先,有必要记住使用redux saga和fork之类的效果实际上并没有创建任何在无限循环中扭曲的线程。它只是组合一系列回调的语法糖,因为yield运算符提供了双方传递的对象。从这个角度来看,强制延迟的问题没有意义 - 因为线程并不存在。
我甚至需要分叉吗?
在适当技能的情况下,通常可以在没有一组调用的情况下执行,并且可以在一个根传奇中执行所有操作。我们的想法是在websocket的当前词汇区域中使用回调函数进行订阅,并期望在延迟承诺的基础上在伪无限循环中获取消息。
从概念上讲,代码看起来大致如此:
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)
}