asynchronous `addImage(...)` design options
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 12.4k
- Forks
- 2.4k
- PR merge metrics
- No merged PRs in 30d
Description
## Motivation
Images can be generated or loaded on demand by listening to the `styleimagemissing` event and then providing the image with `addImage(...)`. The problem is that you need to call `addImage(...)` immediately and it only accepts images that are complete. You have no time to load any new assets!
We need some way of providing images that may not be loaded yet so that we can block tile parsing until that happens.
## Design Alternatives
### Option A: Placeholders
Placeholders block all tiles that use the image. They need to be replaced with the real image or removed. The main disadvantage is that it may be easier to forget to handle the error case.
```js
// add placeholder for image
map.addImage('name', { complete: false });
...
if (error) {
// remove image in case of failure
map.removeImage('name');
} else {
// add loaded image
map.updateImage('name', realImage });
}
```
### Option B: old-fashioned event handlers
Placeholders block all tiles that use the image. They need to be replaced with the real image or removed.
```js
const image = {};
map.addImage('name', image);
...
if (error) {
// remove an image in case of failure
image.onerror();
} else {
// add loaded image
image.width = 10;
image.height = 10;
image.data = ...;
image.onload();
}
```
### Option C: Promise-like
This would accept either real promises or promise-like objects that implement the `then(...)` part of the promise interface.
```js
// With IE support:
let resolve, reject;
map.addImage({ then: function(res, rej) { resolve = res; reject = rej; });
// Without IE support:
map.addImage(new Promise((resolve, reject) => { ... });
...
if (error) {
reject(error);
} else {
resolve(myLoadedImage);
}
```
Alternative: we could also accept the same argument used to construct promises.
```js
map.addImage((resolve, reject) => { ... });
```
### Option D: Callbacks
I'm not sure this follows any existing precedent but it's pretty simple?
```js
const callback = map.addImageAsync('name');
...
if (error) {
callback(error);
} else {
callback(null, myLoadedImage);
}
```
## Design
I'm actually not sure which alternative I prefer. Some have a smaller api footprint. Some would extend better to other potentially async values. Some make error handling more explicit. Some are more familiar.
What do you think?
### Implementation
ImageManager would store placeholder values for all images being loaded. When a worker requests an image that is not yet ready it would get added to the list of pending requests. Each time an image is loaded it would check whether any requests can be fullfilled.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading ImageManager and the addImage API, then trace how styleimagemissing requests reach workers and how pending image requests are handled. Compare the placeholder, event-handler, promise-like, and callback options before choosing an API. Done means one design is selected and the pending requests are fulfilled when an image loads or fails.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- frontend, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100