-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
[v5] Explicit spawn #3148
[v5] Explicit spawn #3148
Changes from 1 commit
29e04ae
4859fe9
abb47d4
39bc706
eb1f5eb
99424c3
d6ffbc9
b7a8751
cee5249
0a3ac9f
9fce5a9
6df48b5
0f5cfb9
5505179
91ecae1
65fe6b4
65a272b
3689875
53e560c
56b7d16
04e228a
ce9971e
3fb32fd
6cdd3cc
6d07555
8f2d906
1fe8923
a9ff1bf
6bf4ea4
69e8b80
b467f67
f0de1ac
eab43a5
ecf9853
fe16e0c
01e9c65
01ffc77
bd8e8e8
9de5049
9b48db2
e69d261
e348d67
2f6d61d
1142173
089c58b
bdaa37d
b3b6a75
eeb1210
c05bd50
6a14905
4ea8080
14a3a0b
664665a
ebff7dc
2c72cde
d0d24dd
ac21c9f
c30059d
5f9f088
575f3d3
b6bb4ae
4b7a74b
e526656
38b34e6
db1079f
a77d4e8
82fc286
6851f62
21ca13c
8b10ff9
fb76fe0
0bea428
9c45c1b
401dbd7
dd54cfe
cc80182
2f3116b
de5ee43
f8f065f
845a7dd
52719b9
31a5021
4318926
d84106d
d4bec9f
8de2ed8
f13f476
1173a61
0a91f87
652658c
a97cd80
fece479
d3274d1
dbfbae9
8655dad
359998d
93a5ada
7e2c649
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -156,9 +156,10 @@ export function fromPromise<T>( | |||
lazyPromise: Lazy<PromiseLike<T>> | ||||
): Behavior<{ type: string }, T | undefined> { | ||||
let canceled = false; | ||||
const resolveEvent = Symbol('resolve'); | ||||
const rejectEvent = Symbol('reject'); | ||||
const resolveEventType = Symbol('resolve'); | ||||
const rejectEventType = Symbol('reject'); | ||||
|
||||
// TODO: add event types | ||||
const behavior: Behavior<any, T | undefined> = { | ||||
transition: (state, event, { self, name }) => { | ||||
if (canceled) { | ||||
|
@@ -171,21 +172,21 @@ export function fromPromise<T>( | |||
|
||||
resolvedPromise.then( | ||||
(response) => { | ||||
self.send({ type: resolveEvent, data: response }); | ||||
self.send({ type: resolveEventType, data: response }); | ||||
}, | ||||
(errorData) => { | ||||
self.send({ type: rejectEvent, data: errorData }); | ||||
self.send({ type: rejectEventType, data: errorData }); | ||||
} | ||||
); | ||||
return undefined; | ||||
case resolveEvent: | ||||
case resolveEventType: | ||||
self._parent?.send( | ||||
toSCXMLEvent(doneInvoke(name, event.data) as any, { | ||||
origin: self | ||||
}) | ||||
); | ||||
return event.data; | ||||
case rejectEvent: | ||||
case rejectEventType: | ||||
const errorEvent = error(name, event.data); | ||||
|
||||
self._parent?.send( | ||||
|
@@ -212,27 +213,66 @@ export function fromObservable<T, TEvent extends EventObject>( | |||
): Behavior<TEvent, T | undefined> { | ||||
let subscription: Subscription | undefined; | ||||
let observable: Subscribable<T> | undefined; | ||||
const nextEventType = Symbol('next'); | ||||
const errorEventType = Symbol('error'); | ||||
const completeEventType = Symbol('complete'); | ||||
let canceled = false; | ||||
|
||||
const behavior: Behavior<TEvent, T | undefined> = { | ||||
transition: (_, event, { observers }) => { | ||||
if (event.type === startSignalType) { | ||||
observable = lazyObservable(); | ||||
subscription = observable.subscribe({ | ||||
next: (value) => { | ||||
observers.forEach((o) => o.next?.(value)); | ||||
}, | ||||
error: (err) => { | ||||
observers.forEach((o) => o.error?.(err)); | ||||
}, | ||||
complete: () => { | ||||
observers.forEach((o) => o.complete?.()); | ||||
} | ||||
}); | ||||
} else if (event.type === stopSignalType) { | ||||
subscription && subscription.unsubscribe(); | ||||
// TODO: add event types | ||||
const behavior: Behavior<any, T | undefined> = { | ||||
transition: (state, event, { self, name }) => { | ||||
if (canceled) { | ||||
return state; | ||||
} | ||||
|
||||
return undefined; | ||||
switch (event.type) { | ||||
case startSignalType: | ||||
observable = lazyObservable(); | ||||
subscription = observable.subscribe({ | ||||
next: (value) => { | ||||
self.send({ type: nextEventType, data: value }); | ||||
}, | ||||
error: (err) => { | ||||
self.send({ type: errorEventType, data: err }); | ||||
}, | ||||
complete: () => { | ||||
self.send({ type: completeEventType }); | ||||
} | ||||
}); | ||||
return state; | ||||
case nextEventType: | ||||
self._parent?.send( | ||||
toSCXMLEvent( | ||||
{ | ||||
type: `xstate.snapshot.${name}`, | ||||
data: event.data | ||||
}, | ||||
{ origin: self } | ||||
) | ||||
); | ||||
return event.data; | ||||
case errorEventType: | ||||
const errorEvent = error(name, event.data); | ||||
self._parent?.send( | ||||
toSCXMLEvent(errorEvent, { | ||||
origin: self | ||||
}) | ||||
); | ||||
return state; | ||||
case completeEventType: | ||||
self._parent?.send( | ||||
toSCXMLEvent(doneInvoke(name), { | ||||
origin: self | ||||
}) | ||||
); | ||||
return state; | ||||
case stopSignalType: | ||||
canceled = true; | ||||
subscription?.unsubscribe(); | ||||
return state; | ||||
default: | ||||
return state; | ||||
} | ||||
}, | ||||
initialState: undefined | ||||
}; | ||||
|
@@ -253,29 +293,57 @@ export function fromEventObservable<T extends EventObject>( | |||
): Behavior<EventObject, T | undefined> { | ||||
let subscription: Subscription | undefined; | ||||
let observable: Subscribable<T> | undefined; | ||||
const nextEventType = Symbol('next'); | ||||
const errorEventType = Symbol('error'); | ||||
const completeEventType = Symbol('complete'); | ||||
let canceled = false; | ||||
|
||||
const behavior: Behavior<EventObject, T | undefined> = { | ||||
transition: (_, event, { self, observers }) => { | ||||
const { _parent: parent } = self; | ||||
|
||||
if (event.type === startSignalType) { | ||||
observable = lazyObservable(); | ||||
subscription = observable.subscribe({ | ||||
next: (value) => { | ||||
parent?.send(toSCXMLEvent(value, { origin: self })); | ||||
}, | ||||
error: (err) => { | ||||
observers.forEach((o) => o.error?.(err)); | ||||
}, | ||||
complete: () => { | ||||
observers.forEach((o) => o.complete?.()); | ||||
} | ||||
}); | ||||
} else if (event.type === stopSignalType) { | ||||
subscription && subscription.unsubscribe(); | ||||
// TODO: event types | ||||
const behavior: Behavior<any, T | undefined> = { | ||||
transition: (state, event, { self, name }) => { | ||||
if (canceled) { | ||||
return state; | ||||
} | ||||
|
||||
return undefined; | ||||
switch (event.type) { | ||||
case startSignalType: | ||||
observable = lazyObservable(); | ||||
subscription = observable.subscribe({ | ||||
next: (value) => { | ||||
self._parent?.send(toSCXMLEvent(value, { origin: self })); | ||||
}, | ||||
error: (err) => { | ||||
self.send({ type: errorEventType, data: err }); | ||||
}, | ||||
complete: () => { | ||||
self.send({ type: completeEventType }); | ||||
} | ||||
}); | ||||
return state; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I rename There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That could be done (i dont mind using state here though). The main point was that this particular behavior wont have non-undefined state/snapshot and when reading through those return statements it looks like it can |
||||
case nextEventType: | ||||
return event.data; | ||||
Comment on lines
+329
to
+330
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an unused code. It should either be removed or this event should be sent from here: xstate/packages/core/src/actors.ts Line 322 in d3274d1
and the self._parent.send(...) should be performed here
|
||||
case errorEventType: | ||||
const errorEvent = error(name, event.data); | ||||
self._parent?.send( | ||||
toSCXMLEvent(errorEvent, { | ||||
origin: self | ||||
}) | ||||
); | ||||
return state; | ||||
case completeEventType: | ||||
self._parent?.send( | ||||
toSCXMLEvent(doneInvoke(name), { | ||||
origin: self | ||||
}) | ||||
); | ||||
return state; | ||||
case stopSignalType: | ||||
canceled = true; | ||||
subscription?.unsubscribe(); | ||||
return state; | ||||
default: | ||||
return state; | ||||
} | ||||
}, | ||||
initialState: undefined | ||||
}; | ||||
|
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.
so... in a way, this should be:
or with the latest changes:
With this design, an observable is really closer to a promise than a machine/callback (they can send events directly to the parent)