This message was deleted.
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.
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.
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.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?
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
> 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.
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
> 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.
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?
Effect handlers are meant to be impure. Event handlers are meant to be pure.
Got it, I'll give these a try. Thanks for the help as always!
Just to let you know, I ended up going with the second approach and using https://github.com/smogg/re-promise