-
Notifications
You must be signed in to change notification settings - Fork 24
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
migrate events #695
migrate events #695
Conversation
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.
What do you think about a curried API that can be used with a pipe
helper a-la https://gist.github.com/cowboyd/384b456e7093462ac0b1c7b33d6213d7
In other words on('message')(websocket)
instead of on(websocket,
message)
lib/deps.ts
Outdated
@@ -1,2 +1,3 @@ | |||
export { assert } from "https://deno.land/std@0.158.0/testing/asserts.ts"; | |||
export * from "https://deno.land/x/continuation@0.1.5/mod.ts"; | |||
export { expectType } from "https://esm.sh/ts-expect@1.3.0"; |
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.
This should probably not be part of the main deps, but maybe put it in test/suite.ts
? That way, when we bundle it for npm for example, it won't be included.
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.
good point, I will change it.
I actually just thought, that I did not bring the tests from the v2
in.
I'll need to add those.
Is the external API the same and only the internals different?
I'm a big fan of pipe so I like it. Do you think it makes sense to support both?
|
We could try and have overloads? How difficult does that make it for you to work out the types? |
Any You just need an effection aware
|
I'm imagining that you would use import { on, pipe } from "effection";
let websocket = new WebSocket('wss://localhost:9000');
yield* pipe(websocket, on("message"), forEach(function*(message) {
console.log('received message from websocket', message)
})); Something about that feels kinda right. Everything is just a combinator, even import { buffer, on, pipe, filter } from "effection";
yield* pipe(
new WebSocket('wss://localhost:9000'),
on('message'),
buffer({ size: 100 }),
map(message => JSON.parse(message.data)),
filter(data => data.type === "result"),
forEach(function*(result) {
console.log('received result from websocket', result)
})
); Perhaps we should get #693 sorted before we get this put in. |
I think Pipe and flow should be a separate PR. |
I think it would be seriously cool to have them here |
lib/events.ts
Outdated
export function once< | ||
T extends EventTarget, | ||
K extends EventList<T> | (string & {}), | ||
>(target: T, name: K): Operation<EventTypeFromEventTarget<T, K>> { | ||
return action(function* (resolve) { | ||
target.addEventListener( | ||
name, | ||
resolve as EventListenerOrEventListenerObject, | ||
); | ||
try { | ||
yield* suspend(); | ||
} finally { | ||
target.removeEventListener( | ||
name, | ||
resolve as EventListenerOrEventListenerObject, | ||
); | ||
} | ||
}); | ||
} |
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 we implement this using first()
on the stream?
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.
A couple of items:
- These should be compatible with
pipe()
, so that you can saypipe(websocket, on("message"))
. That means individually, it would beon("message")(websocket)
. - I don't think we should support
EventEmitter
anymore since now almost every event emitter is also aNodeEventTarget
. It caused troubles when you had event callbacks that passed multiple arguments and led to us having to make aonEmit
andonceEmit
variations. If folks want to use the event emitter api we can provide a separate subscription mechanism. - I think we can express
once()
in terms offirst()
composed withon
. i.e. the "first" item in the event stream:
function once(target, eventName) {
return first(on(eventName)(target));
}
Should once()
be a combinator? I'm not sure.
This is where it gets interesting, in order for any function to work with pipe, it needs to be unary and it needs to be data last So we would need to rewrite function on2<K extends EventList<unknown> | (string & {})>(name: K) {
return function<T extends EventTarget>(target: T): Stream<EventTypeFromEventTarget<T, K>, never> { { We lose all the typing because we rely on the |
nice! |
Can I get a definition of If we want anything to work with pipe then I think anything needs to be a combinator or curried. |
@dagda1 combinator is as you say, a unary function that allows this to be used with |
😭 😭 😭 Do we not get typing because the return function<T extends EventTarget>(target: T): Stream<EventTypeFromEventTarget<T, K>, never> { |
In other words, it should be able to infer if we say: pipe(websocket, on("mess // => runtime knows that "message" is the only valid event name right? |
I'm not sure typescript can infer data last functions. It will work perfectly fine with I have a passing and failing test for both I'll do a bit more digging. I hope I'm wrong about this. |
@cowboyd I've overloaded expectType<Operation<CloseEvent>>(pipe(socket, once("close")));
expectType<Operation<MouseEvent>>(once("click", domElement)); Everything is beautiful with |
@cowboyd I've removed the |
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.
🥳 I love the strong typing so that you get completion on the event names! and combined with the yield*
syntax, where you get strongly type event values, it really does make a difference.
let event = yield* once(websocket, 'close');
Motivation
Migrate
on
andonce
to v3 and add better typing around the event type.Approach
Extract all the
onXXX
events from the event target and allow a fallback to string if none is found.