slopeofhope slopeofhope - 2 months ago 22
Javascript Question

why isn't saga function accepting a request for the 2nd time around?

so I am guessing I am doing something fundamentally wrong. When I upload an image from the browser the first time, the below function triggers but it only happens once. so next time I upload an image, I don't see watchFileReader function running again.. so strange that it is happening..because I am getting other saga function to behave as expected!
Could someone tell me what I may be doing wrong?

export function* watchFileReader() {
const action = yield take("DROP_FILE")
console.log('action', action)
let file = action.file[0];
readFile(file, function(e) {
sessionStorage.removeItem('img')
console.log('alskdjfalsdjkf', e.target.result)
sessionStorage.setItem('img', e.target.result)
})
}

export const readFile = (file, callback) => {
let reader = new FileReader()
reader.onloadend = callback;
reader.readAsDataURL(file)
}

export function* rootSaga() {
yield [
watchFileReader()
]
}

Answer Source

the take effect only gets yielded once. You can either stick the watcher code inside a while loop, or use the takeEvery helper from redux-saga.

Because its a generator function, the saga is suspended until the action is caught by the middleware and yielded again, so its not like you'll have a bunch of infinite loops whirring around in the background hogging cpu.

I use the same design patterns as a lot of the docs, which is to have a 'watcher' saga / process that runs on a loop to take every action dispatched, and fires of a worker saga or process that does the real heavy lifting.

TakeEvery (or takeLatest if you only want the latest one fetched) acts like a forever-running while loop, and each time it gets the action its looking for, forks a new worker, which makes it a non-blocking operation.

export function* fileReaderWorker(action) {
  console.log('action', action)
  let file = action.file[0];
  readFile(file, function(e) {
    sessionStorage.removeItem('img')
    console.log('alskdjfalsdjkf', e.target.result)
    sessionStorage.setItem('img', e.target.result)
  })
}

export function* watchFileReader() {
  yield takeEvery("DROP_FILE", fileReaderWorker)
}
// or the loop version
// while (true) {
//  const action = yield take("DROP_FILE")
//  yield fork(fileReaderWorker, ...args.concat(action))
//}

export const readFile = (file, callback) => {
  let reader = new FileReader()
  reader.onloadend = callback;
  reader.readAsDataURL(file)
}

export function* rootSaga() {
  yield [
    watchFileReader()
  ]
}