re-frame

Slackbot 2024-04-28T10:37:29.951799Z

This message was deleted.

p-himik 2024-04-28T10:44:51.044269Z

You don't need the ::fetch-bookmark-list-stream event at all if you control the api/get-request function and/or what it uses. You can just use it or a somewhat modified version of it to populate the vector you feed to :fx since it accepts any effects, not just :dispatch. :fx guarantees the order in which effects are executed. But it can't possibly guarantee the order of anything those effects themselves do asynchronously (such as network requests). You already feed idx to the event that deals with results of those stream requests - just use it to insert data at the right index instead of adding it to the end of the list.

p-himik 2024-04-28T10:46:04.157649Z

A couple of unrelated notes: • merge on vectors is confusing - conj can be used instead. In your case, apply merge can be replaced with into. • #(identity ...) is also confusing - (fn [x] ...) is both shorter and more legible.

migalmoreno 2024-04-28T11:04:10.297249Z

Thanks. api/get-request is just a wrapper around :http-xhrio . I usually have these fetching functions separate from the rest of the logic in case I'll want to reuse them later, but you're right that in this case it's unnecessary. Yeah, the idx is used for the playlists, not the streams in them, so that items in the first playlist (Liked Streams) will get always get merged in the first playlist, and subsequent streams get added to new playlists. But I see your point about adding an index for each stream and I'm going to give it a shot. I guess more generally I wanted to better tell the difference between this enqueueing of fx and using promises like this:

async addImportedPlaylist(playlist) {
            let newPlaylist = await createPlaylist(playlist.id);
            let videoIds = playlist.videos.map(video => video.url);
            await addVideosToPlaylist(newPlaylist.playlistId, videoIds);
}
Which as far as I know will do everything asynchronously, whereas the re-frame approach doesn't.

migalmoreno 2024-04-28T11:07:42.801529Z

I also wanted to add a notification once all playlists have been imported and the items in them have been refetched, how would I go about signaling this?

migalmoreno 2024-04-28T11:08:18.951379Z

The only thing that comes to mind for these kind of tasks is https://github.com/day8/re-frame-async-flow-fx, but in my case I'm using the same effect handler many times instead of different ones

p-himik 2024-04-28T11:13:44.232679Z

> Which as far as I know will do everything asynchronously, whereas the re-frame approach doesn't. It will also do everything asynchronously. Re-frame's queue is async in the sense that it gets run only when it's allowed to. And it can't go around async JS API. > I also wanted to add a notification once all playlists have been imported and the items in them have been refetched, how would I go about signaling this? Two reasonable options: • Have an explicit or an implicit counter. Explicit - something like :tasks-remaining 7. Implicit - something like :results [...] where the actual counter is (count results) • If you don't care about whether re-frame can see the internals of the stream fetching process or not (e.g. for re-frame-10x or for some interceptors), you can combine all logic into a single function that's independent from re-frame. From the re-frame's perspective, it will be like calling js/fetch, maybe with some progress reporting like :on-step (fn ...). Don't use re-frame-async-flow-fx, it's not for these kinds of workflows.

migalmoreno 2024-04-28T12:42:18.452059Z

Gotcha, thanks for the clarification. With the first approach I understand I would have a counter for the number of streams left to fetch, and that I would increase this on the on-success callback of each, but where would I check for the tasks-remaining? The second approach is simpler, if I understand correctly. I basically would delegate all the fetching logic to an async function (e.g. getImportedPlaylists) which could compute all the streams for each playlists using standard JS async utils (like the example I showed above) and return the playlists when the Promise is resolved. I would then call this function in a re-frame effect handler and simply dispatch as many ::add-bookmark-list effect handlers as there are playlists in the Promise response

p-himik 2024-04-28T12:43:40.323659Z

> but where would I check for the tasks-remaining? Depends on why you need that value. Probably in one of the events that also changes that value. If the value after the change is 0, some other event is triggered.

migalmoreno 2024-04-28T12:48:34.046889Z

Wrt to the second approach, wouldn't having an async function to retrieve the playlists info (the one analogous to js/fetch) being called in an effect handler violate its purity?

p-himik 2024-04-28T12:49:26.183619Z

Effect handlers are meant to be impure. Event handlers are meant to be pure.

migalmoreno 2024-04-28T12:50:20.099239Z

Got it, I'll give these a try. Thanks for the help as always!

👍 1
migalmoreno 2024-04-28T18:28:37.327609Z

Just to let you know, I ended up going with the second approach and using https://github.com/smogg/re-promise

👍 1