javascript - How to tie emitted events events into redux-saga? -
i'm trying use redux-saga connect events pouchdb react.js application, i'm struggling figure out how connect events emitted pouchdb saga. since event uses callback function (and can't pass generator), can't use yield put() inside callback, gives weird errors after es2015 compilation (using webpack).
so here's i'm trying accomplish, part doesn't work inside replication.on('change' (info) => {}).
function * startreplication (wrapper) { while (yield take(database_set_configuration)) { yield call(wrapper.connect.bind(wrapper)) // returns promise, or false. let replication = wrapper.replicate() if (replication) { replication.on('change', (info) => { yield put(replicationchange(info)) }) } } } export default [ startreplication ]
as nirrek explained it, when need connect push data sources, you'll have build event iterator source.
i'd add above mechanism made reusable. don't have recreate event iterator each different source.
the solution create generic channel put , take methods. can call take method inside generator , connect put method listener interface of data source.
here possible implementation. note channel buffers messages if no 1 waiting them (e.g. generator busy doing remote call)
function createchannel () { const messagequeue = [] const resolvequeue = [] function put (msg) { // waiting message ? if (resolvequeue.length) { // deliver message oldest 1 waiting (first in first out) const nextresolve = resolvequeue.shift() nextresolve(msg) } else { // no 1 waiting ? queue event messagequeue.push(msg) } } // returns promise resolved next message function take () { // have queued messages ? if (messagequeue.length) { // deliver oldest queued message return promise.resolve(messagequeue.shift()) } else { // no queued messages ? queue taker until message arrives return new promise((resolve) => resolvequeue.push(resolve)) } } return { take, put } } then above channel can used anytime want listen external push data source. example
function createchangechannel (replication) { const channel = createchannel() // every change event call put on channel replication.on('change', channel.put) return channel } function * startreplication (getstate) { // wait configuration set. can happen multiple // times during life cycle, example when user wants // switch database/workspace. while (yield take(database_set_configuration)) { let state = getstate() let wrapper = state.database.wrapper // wait connection work. yield apply(wrapper, wrapper.connect) // trigger replication, , keep promise. let replication = wrapper.replicate() if (replication) { yield call(monitorchangeevents, createchangechannel(replication)) } } } function * monitorchangeevents (channel) { while (true) { const info = yield call(channel.take) // blocks until promise resolves yield put(databaseactions.replicationchange(info)) } }
Comments
Post a Comment