Summary
The preloadEngagementZoneImages() method in modal.ts uses a fail-fast strategy: if any single engagement zone image fails to load, the entire promise rejects and no engagement zones are ever displayed. This means one broken image URL silently disables all engagement zones for that session.
Affected Code
src/modal/modal.ts, lines 198–222:
private preloadEngagementZoneImages(): Promise<void> {
return new Promise((resolve, reject) => {
let loadedImages = 0;
const imageUrls = ...;
imageUrls.forEach((url) => {
const img = new Image();
img.src = url;
img.onload = () => {
loadedImages++;
if (loadedImages === imageUrls.length) {
this.handleImageLoad(); // Only called if ALL succeed
resolve();
}
};
img.onerror = () => {
console.error(`Image failed to load: ${url}`);
reject(new Error(`Image failed to load: ${url}`)); // Kills everything
};
});
});
}
Problem
- A user configures 5 engagement zone images; 1 URL is broken (expired CDN link, typo, etc.)
- The
onerror handler fires and rejects the promise
handleImageLoad() is never called → _imageLoaded stays false → shimmer placeholder shown forever
- The 4 perfectly valid engagement zones are never displayed
- No error feedback is visible to the end user or the host application
Suggested Implementation
Replace the all-or-nothing approach with a resilient loading strategy:
private async preloadEngagementZoneImages(): Promise<void> {
const imageUrls = this._engagementZones.length > 0
? this._engagementZones.map((zone) => zone.image)
: [Constant.url.defaultEngagementImage];
const results = await Promise.allSettled(
imageUrls.map((url) => new Promise<string>((resolve, reject) => {
const img = new Image();
img.src = url;
img.onload = () => resolve(url);
img.onerror = () => reject(new Error(`Failed: ${url}`));
}))
);
// Filter engagement zones to only those with successfully loaded images
const loadedUrls = new Set(
results
.filter((r): r is PromiseFulfilledResult<string> => r.status === 'fulfilled')
.map((r) => r.value)
);
if (this._engagementZones.length > 0) {
this._engagementZones = this._engagementZones.filter(
(zone) => loadedUrls.has(zone.image)
);
}
if (loadedUrls.size > 0) {
this.handleImageLoad();
}
}
Expected Impact
Summary
The
preloadEngagementZoneImages()method inmodal.tsuses a fail-fast strategy: if any single engagement zone image fails to load, the entire promise rejects and no engagement zones are ever displayed. This means one broken image URL silently disables all engagement zones for that session.Affected Code
src/modal/modal.ts, lines 198–222:Problem
onerrorhandler fires and rejects the promisehandleImageLoad()is never called →_imageLoadedstaysfalse→ shimmer placeholder shown foreverSuggested Implementation
Replace the all-or-nothing approach with a resilient loading strategy:
Expected Impact