Assume that you have a saga that fetches a list of items. For each fetched item you also need a companion object. The pseudo-code below fetches some users from an API and for each user is emitting a new action to fetch her avatar.
function* fetchUsers() {
try {
const users = yield call(getUsers)
yield all(
users.map(({id}) => id).map(id => put(fetchUserAvatar(id)))
)
yield put('FETCH_USER_SUCCESS')
} catch(e) {
yield put('FETCH_USER_FAILURE')
}
}
I would like to emit FETCH_USER_SUCCESS
only when all avatars have been fetched i.e. fetchUserAvatar
saga has emitted either FETCH_USER_AVATAR_SUCCESS
or FETCH_USER_AVATAR_FAILURE
.
So, I implemented the following solution:
function* fetchUsers() {
try {
const users = yield call(getUsers)
yield all(
users.map(({id}) => id).map(id => put(fetchUserAvatar(id)))
)
for(let i = 0; i < users.length; i++) {
yield take(['FETCH_USER_AVATAR_SUCCESS', 'FETCH_USER_AVATAR_FAILURE'])
}
yield put('FETCH_USER_SUCCESS')
} catch(e) {
yield put('FETCH_USER_FAILURE')
}
}
which feels a little ugly to me. Is there any effect such as takeN
or a similar technique where I can wait for N actions to be emitted before proceeding?
Or is there any alternative solution for the above problem?