Skip to content

Commit

Permalink
Add caching for custom markers form URLs (#177)
Browse files Browse the repository at this point in the history
* add caching for custom markers form URLs

* clean up caching logic

* add beta version tag
  • Loading branch information
kochis authored Aug 9, 2024
1 parent f1c901e commit 481dabf
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 29 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Radar.initialize('prj_test_pk_...', { /* options */ });
Add the following script in your `html` file
```html
<script src="https://js.radar.com/v4.3.4/radar.min.js"></script>
<script src="https://js.radar.com/v4.3.5-beta.0/radar.min.js"></script>
```

Then initialize the Radar SDK
Expand All @@ -73,8 +73,8 @@ To create a map, first initialize the Radar SDK with your publishable key. Then
```html
<html>
<head>
<link href="https://js.radar.com/v4.3.4/radar.css" rel="stylesheet">
<script src="https://js.radar.com/v4.3.4/radar.min.js"></script>
<link href="https://js.radar.com/v4.3.5-beta.0/radar.css" rel="stylesheet">
<script src="https://js.radar.com/v4.3.5-beta.0/radar.min.js"></script>
</head>

<body>
Expand All @@ -98,8 +98,8 @@ To create an autocomplete input, first initialize the Radar SDK with your publis
```html
<html>
<head>
<link href="https://js.radar.com/v4.3.4/radar.css" rel="stylesheet">
<script src="https://js.radar.com/v4.3.4/radar.min.js"></script>
<link href="https://js.radar.com/v4.3.5-beta.0/radar.css" rel="stylesheet">
<script src="https://js.radar.com/v4.3.5-beta.0/radar.min.js"></script>
</head>

<body>
Expand Down Expand Up @@ -130,8 +130,8 @@ To power [geofencing](https://radar.com/documentation/geofencing/overview) exper
```html
<html>
<head>
<link href="https://js.radar.com/v4.3.4/radar.css" rel="stylesheet">
<script src="https://js.radar.com/v4.3.4/radar.min.js"></script>
<link href="https://js.radar.com/v4.3.5-beta.0/radar.css" rel="stylesheet">
<script src="https://js.radar.com/v4.3.5-beta.0/radar.min.js"></script>
</head>

<body>
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "radar-sdk-js",
"version": "4.3.4",
"version": "4.3.5-beta.0",
"description": "Web Javascript SDK for Radar, location infrastructure for mobile and web apps.",
"homepage": "https://radar.com",
"type": "module",
Expand Down
97 changes: 78 additions & 19 deletions src/ui/RadarMarker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,34 @@ interface ImageOptions {
height?: number | string;
}

// cache URL loaded markers
const IMAGE_CACHE = new Map<string, 'pending' | 'failed' | Blob>();

const useCachedImage = (url: string, timeoutMS: number = 5000): Promise<Blob> => new Promise((resolve, reject) => {
if (!IMAGE_CACHE.has(url)) { // nothing in cache
IMAGE_CACHE.set(url, 'pending'); // request in flight
return reject('miss');
}

const start = Date.now();
const interval = setInterval(() => {
const cachedData = IMAGE_CACHE.get(url);
if (cachedData === 'pending') {
if ((Date.now() - start) > timeoutMS) { // cache lookup took too long
clearInterval(interval);
reject('timed out');
}
} else if (cachedData === 'failed') { // request failed
clearInterval(interval);
reject('failed');

} else { // return data
clearInterval(interval);
resolve(cachedData as Blob);
}
}, 100);
});

const createImageElement = (options: ImageOptions) => {
const element = document.createElement('img');
element.src = options.url!;
Expand Down Expand Up @@ -97,33 +125,64 @@ class RadarMarker extends maplibregl.Marker {

const onError = (err: any) => {
Logger.error(`Could not load marker: ${err.message} - falling back to default marker`);
IMAGE_CACHE.set(markerOptions.url as string, 'failed'); // mark as failed
this._element.replaceChildren(...Array.from(originalElement.childNodes));
}

// custom URL image
if (markerOptions.url) {
fetch(markerOptions.url)
.then(res => {
if (res.status === 200) {
res.blob()
.then(onSuccess)
.catch(onError);
} else {
onError(new Error(res.statusText));
const loadImage = () => { // fetch marker data from URL
fetch(markerOptions.url as string)
.then(res => {
if (res.status === 200) {
res.blob()
.then((data) => {
IMAGE_CACHE.set(markerOptions.url as string, data); // cache data
onSuccess(data);
})
.catch(onError);
} else {
onError(new Error(res.statusText));
}
})
.catch(onError)
};

// attempt to use cached data, otherwise fetch marker image data from URL
useCachedImage(markerOptions.url)
.then(onSuccess)
.catch((reason: 'miss' | 'timedout' | 'failed' | Error) => {
if (reason !== 'miss') {
Logger.debug(`RadarMarker: cache lookup for ${markerOptions.url}: ${reason}`);
}
})
.catch(onError)
loadImage();
});
}

// Radar hosted image
if (markerOptions.marker) {
// fetch custom marker
Http.request({
method: 'GET',
version: 'maps',
path: `markers/${markerOptions.marker}`,
responseType: 'blob',
})
.then(({ data }) => onSuccess(data))
.catch(onError);
const loadMarker = () => {
Http.request({
method: 'GET',
version: 'maps',
path: `markers/${markerOptions.marker}`,
responseType: 'blob',
})
.then(({ data }) => {
IMAGE_CACHE.set(markerOptions.url as string, data); // cache data
onSuccess(data)
})
.catch(onError);
};

useCachedImage(markerOptions.marker as string)
.then(onSuccess)
.catch((reason: 'miss' | 'timedout' | 'failed' | Error) => {
if (reason !== 'miss') {
Logger.debug(`RadarMarker: cache lookup for ${markerOptions.marker} ${reason}`);
}
loadMarker();
});
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export default '4.3.4';
export default '4.3.5-beta.0';

0 comments on commit 481dabf

Please sign in to comment.