-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correct way to close an eventChannel on saga termination #940
Comments
I think its the best solution, its simple + explicit. There are 2 ways of closing the channel:
The latter snippet satisfies your requirements, right? If so then everything is correct. If not - I dont exactly see how now, please describe the usage more so I can try to help :) |
I got it working using this code: export default function* authSaga() {
const authChannel = eventChannel(emit => {
const unsubscribe = firebase.auth().onAuthStateChanged(
user => emit({ user }),
error => emit({ error })
)
return unsubscribe;
});
try {
yield takeLatest(authChannel, handleSyncTask);
} finally {
if (yield cancelled()) authChannel.close();
}
} So I'm blocking due to the cancelled effect in the finally block. I didn't think this was necessary because I thought the finally block would only be executed once all forked tasks from the saga terminate which is never since I'm using takeLatest which internally uses a while(true) loop. So basically I only have a problem understanding the library which is why I will close the issue now. Maybe you could still try to clear up my misunderstanding here ? 😀 |
That seems not right,
|
Yes the second snippet was fine. I didn't want to use it since it looks like it's reimplementing |
Its because finally block isnt anything special here. Itd just old plain try/catch/finally situation with exception that finally might be called when ur task terminates. You would have to block on something for it to work cause otherwise ur saga gets resumed with task descriptor as the result of yielding takeLatest and goes on right into ur finally block cause u have wrapped it with try like this. This seems though like a legitimate use case for join() as self-join. Need to think about this more. Would propose you to just join(task) after yielding takeLatest |
Thanks @Andarist using |
Apologies to revive a closed issue but I was having a similar issue. The channel in previous function calls wasn't getting closed since Also, would it be possible to handle these kinds of situations within the Unless it is implied that you should be doing cleanup within a |
The correct approach is imgo the one mentioned here.
Could you give an example you have in mind?
Not rly, you probably want to create a channel before hand and pass it to |
This is outdated, but I would like a comment on this implementation. function* saga() {
// main saga
yield spawn(watchAuth);
}
function* watchAuth() {
const channel = eventChannel((emit) => {
auth.listen((action) => emit(action));
return () => {
// unsubscribe
}
});
try {
const task = yield takeLatest(channel, onAuthAction);
yield join(task);
}
finally {
channel.close();
}
} Since, try {
yield takeLatest(channel, onAuthAction); // returns immediately
}
finally {
if (yield cancelled()) { // never true
channel.close(); // never executed
}
} |
I have this simple authSaga which should run during the whole application lifetime:
Only as soon as the app (I'm using react-native) is closed, the finally block should be executed. In reality however it is closed immediately. I looked at the implementation of
takeLatest
and I understand why it does that. Because the outermost task is forked. That's also why implementing takeLatest myself like this works as expected:The docs however state that The parent will terminate after all launched tasks terminate so I didn't expect the finally block to be executed before the saga terminates. Is there some other clever way to close the channel as soon as the saga terminates ?
The text was updated successfully, but these errors were encountered: