-
Notifications
You must be signed in to change notification settings - Fork 122
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
Cmd.setTimeout, Cmd.setInterval #232
Conversation
e5f939d
to
4a32bcc
Compare
I like the thought behind this, but I'd like to see it be more generic. I think it would be good to build in support for intervals as well as timeouts, and also to support cancellation. Without those, I wouldn't feel comfortable adding it to the API because a timeout that can't be cancelled is going to shoot a lot of people in the foot (and you can do this pretty easily with Cmd.run). I also think it would be good to see if we could just make all effects delayable, rather than make individual ones for action. Here's an API idea I had.
and then you could use the scheduled action creator to store the timeout id in case you wanted to cancel it later. And the interval option (open to other naming suggestions), would control whether it was a timeout or interval. Thoughts? |
Great ideas to make this more general. Scheduling intervals is something we have in our code, and it always feels more awkward that it should be. My original thought was that you can use
Alternatively I would pick a similar name, but keep the APIs separate: |
@bdwain I implemented Edit: Oops, I forgot the cancel method too |
Sorry for the delay in looking at this. With everything going on in the world I lost track of things. I think I'm torn between the name delay and setTimeout/setInterval. But i definitely like them both more than schedule. I'm also torn between having 2 separate Cmd types or one with a boolean option to switch between the two. I feel like there's cognitive overhead when you add extra Cmd types. Parallel and non-parallel lists used to be two different command types, but then we combined them into one and I think it worked better (See discussion here) I think we should either do Other than that, the API seems good to me, except I'd like to have the third parameter be an options object. I've had that come back to bite me too many times. We'll want to add some option in the future but having a never ending parameter list is hard to use. Also, while otherCmd and the number of milliseconds is required, the action creator is not. I'll comment on implementation details, but I like the direction this is heading. |
I polled everyone I work with and they all prefer setTimeout/setInterval also. I think that is a good way to name it |
Hey @bdwain. I'm also sorry for the delay. I lost some github notifications and didn't check up on this. I also agree that Are you okay with these names?
The other option is to have a single type Edit: I've decided it's best to go with one unified command type ("DELAY"). The implementation is done unless we find any other big issues. |
ah yea I guess we do want clearTimeout and clearInterval cmds also. As far as separate or shared types, I'll defer to you on that one since i haven't done a ton of typescript yet. Though I'm curious what @nweber-gh thinks. |
sorry didn't mean to close this. the code looks good. Besides my few comments, and the conflicts that got introduced from #235, I think this is probably good to go |
also, if you end up merging before I look at this again, please remember to squash before you merge |
also, don't forget to use the wrappedDispatch function as discussed in https://github.com/redux-loop/redux-loop/pull/235/files#r397694600 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionally I think that the single delay interface is probably fine.. however, I feel a bit weird about the TypeScript definition not matching the public API. The other main Cmd generators returns a type that matches the function and it feels like it’ll add a bit of cognitive delay to have to process what a DelayCmd is instead of just seeing a SetTimeoutCmd.
But.. I also don’t have a personal problem with the abstraction. It makes sense, it just adds an extra mental jump that folks have to make when tracing through the types.
@laszlopandy do you think you'll get back to this soon? I'd love to release a new version soon |
@bdwain Yep. I was busy with family stuff recently but I'm been thinking about how to finish this up. I'll set aside some time this week. |
sounds good thanks @laszlopandy |
TODO:
|
81826e6
to
ab8d10b
Compare
a12b705
to
daca72c
Compare
simulate(timerId: number, nestedSimulation?: CmdSimulation | MultiCmdSimulation): A[] | A | null | ||
} | ||
|
||
export interface SetIntervalCmd<A extends Action = never> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we support passing arguments, similar to RunCmd
, for the delayed commands? Both setTimeout
and setInterval
support an arbitrary set of args, which get sent to the callback function, so I think it would make sense to support args
in these commands as well.
example
setTimeout((message, count) => console.log(message, count), 500, 'hello world', 7);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or.. Perhaps that doesn't make sense, since this is delaying other commands. We could just delay a RunCmd
to get args. It might make sense to support args
to pass to the scheduleActionCreator
however. What do you guys think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I think the callback args aren't really necessary. Since this is taking other Cmds, we can just pass those args directly to the cmd if needed. And for passing args to the action creator, we can just use arrow functions like we've done with Cmd.run.
const runCmd = Cmd.run(
(message, count) => console.log(message, count),
{args: ['hello world', 500], successActionCreator: whatever}
)
return loop(newState, Cmd.setTimeout(runCmd, 1234, {scheduledActionCreator: id => actionCreator(id, arg, arg2)}))
@bdwain This PR is done, feel free to merge it whenever you are ready. |
test/cmd.spec.js
Outdated
await expect(result).resolves.toEqual([ | ||
actionCreator2(expect.anything()) | ||
]); | ||
await dispatchPromise; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we mock the timers and wait for those rather than just resolve as soon as dispatch is called? That would allow us to verify we're actually waiting for the right amount of time, and would allow us to improve the setInterval test by verifying it actually runs multiple times
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, do you have a nice way to do this, or would you just overwrite the global setInterval
and restore it in an after block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jest can do this https://jestjs.io/docs/en/timer-mocks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, please check it again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you do the same thing for setTimeout? basically the same as the setInterval test, except we verify that we don't dispatch more actions after the time elapses again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
thanks @laszlopandy ! |
Add a new type of action which schedules another command to be dispatched using
setTimeout()
orsetInterval()
. This is a very useful feature for starting/stopping animations and scheduling timeouts.Having an explicit action type makes the intention of the code clear -- you don't need to use
Cmd.run()
for something which is not an external side-effect.