Skip to content

Instantly share code, notes, and snippets.

@jpgorman
Last active October 20, 2021 12:30
Show Gist options
  • Save jpgorman/f49501076a13cecfaa17d30e8d569be0 to your computer and use it in GitHub Desktop.
Save jpgorman/f49501076a13cecfaa17d30e8d569be0 to your computer and use it in GitHub Desktop.
Example of using redux-saga eventChannel with axios/fetch etc
import {eventChannel, END} from 'redux-saga'
function createUploaderChannel(key, files){
return eventChannel(emit => {
const onProgress = ({total, loaded}) => {
const percentage = Math.round((loaded * 100) / total)
emit(percentage)
}
axios.post('url', files, {
requestId: key,
uploadProgress: onProgress,
}).then(() => {
emit(END)
}).catch(err => {
emit(new Error(err.message))
emit(END)
})
const unsubscribe = () => {}
return unsubscribe
})
}
function* uploadProgressWatcher(fileName, channel) {
while(true){
try{
const progress = yield take(channel)
yield put(actions.uploadFiles.progress(progress))
}
catch(err){
yield put(actions.uploadFiles.progress(err))
}
finally{
if(yield cancelled()) channel.close()
}
}
}
function* uploadFile(fileName, index, files) {
try{
const formData = new FormData()
formData.append('files', files[fileName])
const uploadChannel = yield call(createUploaderChannel, fileName, formData)
yield fork(uploadProgressWatcher, fileName, uploadChannel)
}
catch(err){
yield* actions.uploadFiles.failure(err)
}
}
function* uploadFiles({payload}) {
const {files} = payload
yield put(actions.uploadFiles.progress(payload))
yield all(
Object.keys(files).map(uploadFile)
)
}
export default function*() {
takeLatest(actions.uploadFiles, uploadFiles)
}
@hariDasu
Copy link

@a-buyankin
Copy link

in eventChannel subscribe should return a function to unsubscribe

@OliverWall
Copy link

Thanks !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment