Step 7. Subscribe to events
The Ping (ForgeRock) Login Widget has a number of asynchronous APIs, which are designed around an event-centric observable pattern. It uses Svelte’s simplified, standard observable implementation called a "store".
These Svelte stores are embedded into the Ping (ForgeRock) Login Widget itself. They are not a dependency that your app layer needs to import or manage. |
For more information on Svelte stores, refer to the Svelte documentation.
This observable pattern is optimal for UI development as it allows for a dynamic user experience. You can update your application in response to the events occurring within the Ping (ForgeRock) Login Widget. For example, the Ping (ForgeRock) Login Widget has events such as "loading", "completed", "success", and, "failure".
Assign an observable
You can create a variable and assign the observable to it:
const userInfoEvents = user.info();
Subscribe to observable events
An observable is a stream of events over time. The Ping (ForgeRock) Login Widget invokes the callback for each and every event from the observable, until you unsubscribe from it.
Use the subscribe()
method on your variable to observe the event stream:
userInfoEvents.subscribe((event) => {
if (event.loading) {
console.log('User info is being requested from server');
} else if (event.successful) {
console.log('User info request was successful');
console.log(event.response);
} else if (event.error) {
console.error('User info request failed');
console.error(event.error.message);
}
});
For information on the events each observable returns, refer to the API reference.
Unsubscribe from an observable
Unlike a JavaScript promise, an observable does not resolve and then get cleaned up after completion.
You need to unsubscribe from an observable if it is no longer needed. This is especially important if you are subscribing to observables in a component that gets created and destroyed many times over. Subscribing to an observable over and over without unsubscribing creates a memory leak.
To unsubscribe, assign the function that is returned from calling the subscribe()
method to a variable. Call this variable at a later time to unsubscribe from the obeservable.
const unsubUserInfoEvents = userInfoEvents.subscribe((event) => console.log(event));
// ...
// Unsubscribe when no longer needed
unsubUserInfoEvents();
You do not need to unsubscribe from observables if you subscribe to observables in a top-level component of your app that is only initiated once, and is retained over the lifetime of your application.
A good location in which to subscribe to observables might be the central state management component or module of your application.
Get current local values
The Ping (ForgeRock) Login Widget stores a number of important values internally.
You can get the current values stored within the Ping (ForgeRock) Login Widget without subscribing to any future events or their resulting state changes by calling subscribe()
and then immediately calling its unsubscribe method:
// Create variable for user info
let userInfo;
// Call subscribe, get the current local value, and then immediately call the returned function
userInfoEvents.subscribe((event) => (userinfo = event.response))(); // <-- notice the second pair of parentheses
Get updated values
You can ask the Ping (ForgeRock) Login Widget to request new, fresh values from the server, rather than just what it has stored locally, by calling the observable action methods, such as get
.
userInfoEvents.get();
When using the observable pattern, you can call this method and forget about it. The get causes any subscribe
callback functions you have for the observable to receive the events and new state.
The subscribe
can exist before or after this get
call, and it will still capture the resulting events.
Use promises rather than observables
We recommend observables, but the choice is up to you.
All of the Ping (ForgeRock) Login Widget APIs that involve network calls have an alternative promise implementation that you can use.
The following example again shows userInfoEvents
but converted to use promises:
// async-await
let userInfo;
async function example() {
try {
userInfo = await userInfoEvents.get();
} catch (err) {
console.log(err);
}
}
// Promise
let userInfo;
userInfoEvents
.get()
.then((data) => (userInfo = data))
.catch((err) => console.log(err));