Bug description
The embedded dashboard continues to make fetchGuestToken
calls even after the component containing it has been destroyed and unmount()
has been called. This leads to unnecessary network requests and potential memory leaks in Single Page Applications (SPAs).
@superset-ui/embedded-sdk version: 0.1.3 Framework: Angular 16 Browser: 136.0.7103.114
Steps to Reproduce
- Create an Angular component that embeds a Superset dashboard using embedDashboard()
- Configure the dashboard with fetchGuestToken callback
- Navigate to the component and let the dashboard load successfully
- Navigate away from the component (triggering ngOnDestroy)
- Call unmount() on the dashboard instance in the cleanup method
- Wait approximately 5 minutes
- Observe network requests in browser DevTools
Expected Behavior
After calling unmount()
on the dashboard instance, no further fetchGuestToken
calls should be made, and all internal timers/intervals should be cleared.
Actual Behavior
The fetchGuestToken callback continues to be invoked approximately 5 minutes after navigation, even though:
- The component has been destroyed
- unmount() was called on the dashboard instance
- The DOM container has been cleared
Code Example
export class AnalyticsComponent implements OnInit, OnDestroy {
private currentDashboard: EmbeddedDashboard | null = null;
async ngOnInit() {
this.currentDashboard = await embedDashboard({
id: 'dashboard-id',
supersetDomain: 'https://superset.example.com',
mountPoint: this.containerElement,
fetchGuestToken: () => this.fetchGuestToken(), // This continues to be called!
dashboardUiConfig: {
hideTitle: true,
filters: { expanded: false }
}
});
}
ngOnDestroy() {
this.cleanup();
}
private cleanup() {
if (this.currentDashboard) {
try {
this.currentDashboard.unmount(); // Called but doesn't stop token fetching
this.currentDashboard = null;
} catch (error) {
console.error('Error unmounting dashboard:', error);
}
}
// Clear container
if (this.containerElement) {
this.containerElement.innerHTML = '';
}
}
private async fetchGuestToken(): Promise<string> {
console.log('Token fetch called - this should not happen after unmount!');
// ... token fetching logic
}
}
Potential Root Cause
The embedded dashboard appears to maintain internal timers/intervals for token refresh that are not properly cleared by the unmount() method. This suggests:
- Internal setTimeout/setInterval calls are not being tracked and cleared
- The
unmount()
method may not be cleaning up all dashboard lifecycle processes - Async operations initiated before unmount may still complete after unmount
Screenshots/recordings
No response
Superset version
master / latest-dev
Python version
3.9
Node version
16
Browser
Chrome
Additional context
No response
Checklist
- [x] I have searched Superset docs and Slack and didn't find a solution to my problem.
- [x] I have searched the GitHub issue tracker and didn't find a similar bug report.
- [ ] I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.
Comment From: dosubot[bot]
Hi @NewtonFernandis! I'm Dosu and I’m helping the superset team.
This is a real bug in the current @superset-ui/embedded-sdk: the SDK schedules fetchGuestToken refreshes using setTimeout, but the unmount() method only clears the DOM and does not cancel or track these timers. As a result, fetchGuestToken continues to be called after unmount(), even after the Angular component is destroyed. There is no built-in mechanism to stop these background refreshes or cancel in-flight async operations after unmount()—which can lead to memory leaks and unwanted network requests in SPAs like Angular apps. You can see this in the SDK code, where setTimeout is used recursively for token refresh, but unmount() does not clear these timers or provide any cleanup logic for them (source).
There are no official workarounds or best practices documented for this scenario. As a temporary mitigation, you could try monkey-patching the SDK to track and clear the timer yourself, or wrap fetchGuestToken in a guard that disables it after unmount, but these are not officially supported solutions. This is a lifecycle management gap in the SDK and would need to be addressed in the library itself for a robust fix.
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
Comment From: NewtonFernandis
Okay 👍, Thank you.