2017-04-25 191 views
0

在我当前的项目中,我正在处理firebase websocket订阅。不同的组件可以订阅不同的数据,例如,在每个ListItem组件的订单列表中,通过分派componentDidMount中的SUBSCRIBE动作和通过分派componentWillUnmount中的UNSUBSCRIBE动作取消订阅,订阅了该特定项目的websocket“事件”。使用redux-saga处理订阅/取消订阅大量事件

我的传奇故事是这样的:

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

我应该引入某种延迟来给线程一些空间来处理其他事情吗?

首先需要记住的是,使用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) 
}