Skip to content

Commit a5e4e16

Browse files
committed
docs: update readme
1 parent 9c59d6a commit a5e4e16

File tree

1 file changed

+95
-17
lines changed

1 file changed

+95
-17
lines changed

src/2.0/2.0.md

Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,102 @@ import { setOptions, importLibrary } from "@googlemaps/js-api-loader";
2222
const { Map } = await importLibrary("maps");
2323
```
2424

25-
Since wrapping all code working with the maps API into async functions can be
26-
problematic, we also provide an API that can be used in a synchronous context:
25+
## Synchronous API (TBD)
2726

28-
```ts
29-
import {
30-
getImportedLibrary,
31-
isLibraryImported,
32-
} from "@googlemaps/js-api-loader";
33-
34-
try {
35-
// getImportedLibrary throws an Error when the library hasn't been loaded yet
36-
// (otherwise the destructuring of the result wouldn't work)
37-
const { Map } = getImportedLibrary("maps");
38-
} catch (err) {}
39-
40-
// when guarded by isLibraryImported, it's guaranteed to not throw
41-
if (isLibraryImported("maps")) {
42-
const { Map } = getImportedLibrary("maps");
27+
### Motivation
28+
29+
There are a lot of situations where the `importLibrary` function doesn't
30+
work well, since using an async function or promises isn't always a viable
31+
option.
32+
33+
Currently, the only alternative to `importLibrary` is to use the global
34+
`google.maps` namespaces. An additional synchronous API is intended to
35+
provide an alternative way to using the global namespaces while solving some
36+
of the problems that come with using them.
37+
38+
Any synchronous access to the libraries requires developers to make sure the
39+
libraries have already been loaded when the corresponding code is executed.
40+
In practice, this is rarely a big issue.
41+
42+
The exact shape of the synchronous API is to be determined, it could be a
43+
simple Map instance `libraries` or a pair of has/get functions to check for and
44+
retrieve loaded libraries.
45+
46+
### Example 1: helper classes
47+
48+
Imagine some service class that uses the `places` library and the
49+
`PlacesService` to do it's thing.
50+
51+
#### global namespace
52+
53+
This is how it would be written with the global `google.maps` namespace:
54+
55+
```tsx
56+
class PlacesHelper {
57+
private service: google.maps.places.PlacesService;
58+
59+
constructor() {
60+
if (!google.maps.places.PlacesService)
61+
throw new Error("maps api or places library missing");
62+
63+
this.service = new google.maps.places.PlacesService();
64+
}
65+
66+
// ...
67+
}
68+
```
69+
70+
This has two drawbacks:
71+
72+
- having to write out `google.maps.places` for all classes (and
73+
types, but that's a seperate issue) adds a lot of "noise" to the code
74+
- references to the global namespace can't really be minified, and
75+
due to the late loading of the API, a global assignment to a shorthand
76+
name isn't really possible.
77+
78+
#### importLibrary
79+
80+
Since in a constructor, we can't `await` the result of `importLibrary`, the
81+
only way to do this is using the `.then()` function, which drastically
82+
changes the semantics of the code:
83+
84+
```tsx
85+
class PlacesHelper {
86+
private service: google.maps.places.PlacesService | null = null;
87+
88+
constructor() {
89+
importLibrary("places").then(
90+
({ PlacesService }) => (this.service = new PlacesService())
91+
);
92+
}
93+
}
94+
```
95+
96+
Here, the service has to be declared as optional (`| null`) in typescript,
97+
and every other method of the class has to somehow deal with the fact that
98+
the service might not yet have been initialized. Even if the library is
99+
already loaded, it won't be returned until the queued mircotasks and the
100+
handlers for the awaited Promise are executed.
101+
This can even have cascading effects on all classes calling methods of this
102+
class.
103+
104+
#### proposed sync API
105+
106+
A synchronous API would allow us to write the same code we used for
107+
global namespaces, but without the readability problems and without global
108+
namespaces:
109+
110+
```tsx
111+
class PlacesHelper {
112+
private service: google.maps.places.PlacesService = null;
113+
114+
constructor() {
115+
if (!isLibraryImported("places"))
116+
throw new Error("maps api or places library missing");
117+
118+
const { PlacesService } = getImportedLibrary("places");
119+
this.service = new PlacesService();
120+
}
43121
}
44122
```
45123

0 commit comments

Comments
 (0)