00:08:17  * phatedquit (Remote host closed the connection)
02:16:23  * dguttman89joined
05:02:40  * contrahaxjoined
06:50:09  <mikolalysenko>i was thinking today and realized that eventemitters are kind of bullshit
06:50:28  <mikolalysenko>like they're almost never the right solution where they get applied, you're almost always better off just using a callback
06:50:38  <mikolalysenko>and there's so many ways they can go wrong and fuck you up
06:51:15  <mikolalysenko>for example you have this race condition where when you create an emitter you might drop the first few messages if a listener gets added asynchronously
06:51:34  <mikolalysenko>also dispatching from an event emitter is way slower than just calling a function
06:51:53  <mikolalysenko>and event emitters get used for all kinds of stuff that shouldn't be an event emitter
06:52:12  <mikolalysenko>for example, I don't think http or stream should have been based on event emitters
06:52:42  <mikolalysenko>like when are you ever gonna have more than one object listening on a stream or writing into it?
06:52:55  <mikolalysenko>same deal with http. once something writes to the response object, it pretty much owns it
06:53:25  <substack>EventEmitters make it easier to pass objects around with the construction happening elsewhere
06:53:26  <mikolalysenko>and another small thing that sucks with event emitters is you can't get type completion from tools like flow or typescript
06:53:38  <mikolalysenko>substack: i agree, but I think I know a better pattern
06:53:59  <mikolalysenko>what you do is have an object where you first construct it, then have a second method called 'start' or whatever where you pass in an object full of callbacks
06:54:16  <mikolalysenko>http already pretty much works like this anyway. the listen() method is what starts the server
06:54:45  <substack>a lot of this stuff is based on convention. bucking interface tradition only makes it harder for people to use it
06:54:46  <mikolalysenko>in my ideal world, http would not be an event emitter and instead that listen() method would start the server and take all the config callbacks
06:55:00  <substack>I've used APIs like that and they kind of suck
06:55:12  <mikolalysenko>can you give an example
06:55:37  <substack>can't remember the name, but there was an http lib that worked the way you describe
06:57:17  <mikolalysenko>but like http is a good example of a thing that isn't really an event emitter
06:57:26  <mikolalysenko>you can't have 2 emitters write an http response to the same request
06:57:49  <mikolalysenko>event emitters are ok when used appropriately. if you have multiple things that need to subscribe to the same event
06:58:03  <mikolalysenko>the problem is they are way over used in node's core apis
06:58:15  <substack>you can have one that listens for events and writes to a lot
06:58:17  <substack>*log
06:58:44  <mikolalysenko>or you could just make a logging http server that shims the main server and forwards all requests to the child callbacks
07:00:15  <mikolalysenko>same idea with streams, you would just pipe through a logging stream
07:00:31  <substack>pull streams is like that
07:00:44  <mikolalysenko>yeah, and it is better than streams for exactly that reason
07:01:21  <substack>sure it's better in one sense, but much worse because of the lack of interop and how it bucks a lot of convention
07:01:22  <mikolalysenko>i understand that things are the way they are now and i am not advocating changing it
07:01:27  <mikolalysenko>oh i agree
07:01:40  <mikolalysenko>breaking http is a dumb idea
07:02:12  <mikolalysenko>with the benefit of hindsight it seems like maybe this api was badly designed
07:02:34  <mikolalysenko>and personally it sort of helps clarify some stuff that had been bothering me about my own code
07:03:30  <mikolalysenko>for example, i never really liked the way game-shell worked and looking back on it i think at least part of the problem is the event emitter syndrome
07:04:29  <mikolalysenko>it is import to make sure that all callbacks are registered before the protocol is initiated
07:04:53  <mikolalysenko>so i am kind of leaning toward using this: construct -> configure & start pattern
07:05:44  <mikolalysenko>oh and another thing that sucks with event emitters: controlling order of execution is bonkers
07:05:53  <mikolalysenko>this is also related to problems i have with middleware
07:06:18  <mikolalysenko>like it's the same reason i think express/react's middleware sucks
07:08:54  <substack>http is kind of a bad idea so ¯\_(ツ)_/¯
07:09:18  <mikolalysenko>so learn from it and do better next time
07:10:43  <mikolalysenko>like i can't even think of one good example of using event emitters in an api where it doesn't feel like a mistake
07:10:57  <substack>I think event emitters make sense for stateless data where you don't necessarily care about prior events
07:12:03  <substack>but I also haven't been bitten by using event emitters any times I can remember
07:12:45  <mikolalysenko>that's the thing. most common uses of event emitters just configure it once at construction and don't touch it
07:12:57  <mikolalysenko>which is fine, but the api allows you to do a lot more than that
07:13:05  <mikolalysenko>and that extra stuff is really bloated, complicated and useless
07:13:11  <mikolalysenko>and more likely to break if you use it
07:13:30  <mikolalysenko>for example, if you have a 'ready' event you need to catch, you better configure that method in the main callback
07:14:13  <mikolalysenko>(by maincallback i mean in the same time quantum where the event emitter was constructed)
07:15:22  <substack>the same tick
07:15:37  <mikolalysenko>yeah, you know what i mean
07:16:00  <mikolalysenko>most people use emitters that way and it works
07:16:19  <mikolalysenko>but the api is designed around these weird ideas that you might want to not do that, and it makes it really complicated
07:16:52  <mikolalysenko>the general point i'm making is you want to register all handlers and configure the object before you start processing events
07:17:34  <mikolalysenko>and that's the first issue. the second is that multiple handlers doesn't make much sense for most applications of event emitter
07:19:26  <mikolalysenko>it's like event emitters are this way over engineered mess that only creates new opportunities for things to go wrong
07:19:52  <mikolalysenko>simpler approach: hook some callbacks before you start
07:20:39  <mikolalysenko>for example, fs works this way and imo it is a better api
07:22:58  <mikolalysenko>one place where you get forced into using event emitter like apis is from framework hell
07:23:30  <mikolalysenko>for example, in the DOM you have to use addEventListener() because objects are constructed externally
07:23:57  <mikolalysenko>in a more ideal world your code would be the one constructing all the objects you are going to use
07:24:12  <mikolalysenko>which is how things like react work, and also another reason why they're nicer to work with you
07:25:16  <substack>it's nice to have a redux-style event emitter bus with things like react at the same time
07:25:46  <mikolalysenko>but redux isn't really like an event emitter
07:25:48  <substack>for messy problems like UIs where distant elements need to listen and sent messages to each other
07:26:10  <mikolalysenko>it is basically a stream processor
07:26:25  <mikolalysenko>i would say redux is more about getting out of the event emitter paradigm
07:26:46  <mikolalysenko>you get actions from a known set of possibilities and then recursively call reducers/functions to compute the next state
07:27:20  <substack>I think that idea is more simply and concisely implemented with event emitters
07:27:24  <substack>like how choo does it
07:27:41  * serapathquit (Quit: Connection closed for inactivity)
07:27:45  <substack>that's also what I've done with regl a few times and it's pretty nice
07:28:25  <substack>particularly when you might have props set from the outside multiple times and you need to re-bind or re-load things
07:34:28  <mikolalysenko>i can sort imagine what a choo without emitters might look like, it could be event smaller
07:35:30  <mikolalysenko>for example, could kill the middleware in app.use and instead a middleware is just a higher order function; ie `app.use(log()); app.use(myStore());` becomes: `app.use(log(myStore()));`
07:38:55  <mikolalysenko>wow that was a lot of typos
08:20:22  <jfhbrook>promises are a decent replacement for once listeners, not 1:1 but enough shared use cases
08:22:53  <jfhbrook>maybe stating the obvious, but it seems to me events are best when multiple third parties need to be able to react when something happens, multiple times--for instance, for pubsub, the subscriber decides what to do with the event, and there are a ton of them, and an untold number of messages
08:23:15  <jfhbrook>for other cases, like where there would only ever be 1 listener, or 1 event, I think there are often simpler abstractions
08:24:37  <jfhbrook>I don't know that I buy an argument that because you're probably instantiating the subscribers yourself that you /should/ move the event linking logic elsewhere
08:30:18  <jfhbrook>just noticed the scrollback goes way further back than I would have guessed
08:30:28  <jfhbrook>looks like these ideas were already covered in detail, hah
08:32:08  <jfhbrook>speaking of promises and streams, it's viable to build streams using promises, basically Promise[{data, Promise[etc etc
08:32:23  <jfhbrook>someone planted this idea in my head once, I was amused
09:04:45  <mikolalysenko>more garbage for the collector god
09:12:51  <jfhbrook>hah!
10:25:10  * mylesborinsquit (Quit: farewell for now)
10:25:40  * mylesborinsjoined
13:09:06  * ralphtheninjajoined
13:09:06  * ralphtheninjaquit (Client Quit)
14:41:34  * nickpeihljoined
16:17:37  * contrahaxquit (Ping timeout: 255 seconds)
16:19:47  * contrahaxjoined
16:31:53  * contrahaxquit (Quit: Sleeping)
16:45:35  * contrahaxjoined
16:51:18  * nickpeihlquit (Quit: Connection closed for inactivity)
17:57:33  * contrahaxquit (Quit: Sleeping)
18:33:18  * contrahaxjoined
18:40:06  * contraha_joined
18:42:37  * contrahaxquit (Ping timeout: 258 seconds)
18:47:22  * phatedjoined
20:32:43  * phatedquit (Remote host closed the connection)
20:42:06  * phatedjoined
21:42:26  * phatedquit (Remote host closed the connection)
22:36:21  * phatedjoined
22:40:57  * phatedquit (Ping timeout: 240 seconds)