Programming for emacs is interesting because the way you isolate state is very buffer-oriented.
I keep falling into the trap of "Well, I need to have a listener wake up later to handle the results of running this process once it's done. So I'll create a closure that~" no. The process has a process buffer. That buffer has local variables. That's your execution state. You need to know something later? Cram it in a buffer-local variable. Register a sentinel function that will get the process and the sentinel event and have that function get everything it needs from the process's buffer contents and local variables.
It's a lot like programming older-style event-driven JavaScript (before we became afraid of the JS event model and wrapped it behind three frameworks and a local database). Or like programming a videogame with agents and behaviors.
(Every time I sit down to write something big, I have to relearn this because all other programming I do does not work this way).