dvlsg / async-csp

CSP style channels using ES7 async/await
MIT License
317 stars 18 forks source link

What's the best way to cancel things? #22

Open trusktr opened 6 years ago

trusktr commented 6 years ago

What's the recommended way to make cancellable sort of scenarios in an application with async-csp? Basically, suppose we've got any number of things waiting for output from a channel, but the user clicks a "cancel" button. Are there any recommended patterns for cancellation?

dvlsg commented 6 years ago

Depends on what you want to do with any existing / waiting data. Channel#close() will prevent any new values from showing up. Are you looking to ignore any takes which are still waiting on the channel and just send the sentinel (done) value to them instead?

trusktr commented 6 years ago

Are you looking to ignore any takes which are still waiting on the channel and just send the sentinel (done) value to them instead?

Yeah, I think so, so that if something is waiting on a value from take(), then canceling could immediately send the done sentinel so that processes can continue immediately without waiting for the take Promise.

Is something like that already doable?

I'm currently working on a way to organize animation states and transitions, and I'd like for them to be cancellable.

I know I can just use plain promises, and reject things with "sentinel" values, but as you imagine, doing it that way would get messy.

I'm wondering if there's a clean way of organizing this with channels.

I know I can send anything I want through a channel, so I can design my own "sentinel" values to tell the receiving end what's going on.

Let me play with it and see what I come up with using the existing public API

dvlsg commented 6 years ago

My gut is telling me to suggest using Channel#close() and then keep an eye out for that Channel.DONE symbol in any Channel#take() calls, but you won't be able to re-use the channel, in that case. Right now, you'd have to set up another one.

The call to take() will resolve, so you'd still have to wait for it (sort of), but it won't wait for new values to come into the channel -- all outstanding takes should resolve with the Channel.DONE value ASAP, even if there are a bunch queued up.

trusktr commented 6 years ago

In my case, I've got a single process taking, so I ended up just sending false when complete, which made the conditional check less verbose on the taking side.

What if we have a channel, and we'd like a varying and unknown number of takers to take on the receiving side?

F.e., something like this: 10 receivers take() and they all wait... Sender put()s one value then all receivers resolve on the value.... Now 6 receivers take() and wait... Send put()s another single value.

Is each receiver supposed to be responsible for forking the channel in that case?

On Feb 26, 2018 1:41 PM, "dvlsg" notifications@github.com wrote:

My gut is telling me to suggest using Channel#close() and then keep an eye out for that Channel.DONE symbol in any Channel#take() calls, but you won't be able to re-use the channel, in that case. Right now, you'd have to set up another one.

The call to take() will resolve, so you'd still have to wait for it (sort of), but it won't wait for new values to come into the channel -- all outstandings takes should resolve with the Channel.DONE value ASAP, even if there are a bunch queued up.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/dvlsg/async-csp/issues/22#issuecomment-368660503, or mute the thread https://github.com/notifications/unsubscribe-auth/AASKzpA58ldDKWnAepwJPgnmbCuB7jPtks5tYyUBgaJpZM4QV2d9 .

dvlsg commented 6 years ago

Probably the best way of doing it, yes. Shouldn't be too difficult to make an api which appends / returns a newly piped channel when a new consumer shows up. I think Channel#unpipe() and Channel#close() might help you with destructing those connections as well (if necessary). But yes, Channels are not multi-cast / fan out (by design).