Skip to content

Commit 2668baa

Browse files
authored
Merge pull request #217808 from stevemunk/SM-Rest-SDK-Developer-Guides-js
JavaScript developer guide REST SDK
2 parents 228b63e + 242a11a commit 2668baa

File tree

4 files changed

+405
-10
lines changed

4 files changed

+405
-10
lines changed
Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
---
2+
title: How to create Azure Maps applications using the JavaScript REST SDK (preview)
3+
titleSuffix: Azure Maps
4+
description: How to develop applications that incorporate Azure Maps using the JavaScript SDK Developers Guide.
5+
author: stevemunk
6+
ms.author: v-munksteve
7+
ms.date: 11/07/2021
8+
ms.topic: how-to
9+
ms.service: azure-maps
10+
services: azure-maps
11+
---
12+
13+
# JavaScript/TypeScript REST SDK Developers Guide (preview)
14+
15+
The Azure Maps JavaScript/TypeScript REST SDK (JavaScript SDK) supports searching using the [Azure Maps search Rest API][search], like searching for an address, fuzzy searching for a point of interest (POI), and searching by coordinates. This article will help you get started building location-aware applications that incorporate the power of Azure Maps.
16+
17+
> [!NOTE]
18+
> Azure Maps JavaScript SDK supports the LTS version of Node.js. For more information, see [Node.js Release Working Group][Node.js Release].
19+
20+
## Prerequisites
21+
22+
- [Azure Maps account][Azure Maps account].
23+
- [Subscription key][Subscription key] or other form of [authentication][authentication].
24+
- [Node.js][Node.js].
25+
26+
> [!TIP]
27+
> You can create an Azure Maps account programmatically, Here's an example using the Azure CLI:
28+
>
29+
> ```azurecli
30+
> az maps account create --kind "Gen2" --account-name "myMapAccountName" --resource-group "<resource group>" --sku "G2"
31+
> ```
32+
33+
## Install the search package
34+
35+
To use Azure Maps JavaScript SDK, you'll need to install the search package. Each of the Azure Maps services including search, routing, rendering and geolocation are each in their own package.
36+
37+
```powershell
38+
npm install @azure/maps-search
39+
```
40+
41+
Once the package is installed, create a `search.js` file in the `mapsDemo` directory:
42+
43+
```text
44+
mapsDemo
45+
+-- package.json
46+
+-- package-lock.json
47+
+-- node_modules/
48+
+-- search.js
49+
```
50+
51+
### Azure Maps search service
52+
53+
| Service Name  | NPM package  | Samples  |
54+
|---------------|-------------------------|--------------|
55+
| [Search][search readme] | [Azure.Maps.Search][search package] | [search samples][search sample] |
56+
| [Route][js route readme] | [@azure-rest/maps-route][js route package] | [route samples][js route sample] |
57+
58+
## Create a Node.js project
59+
60+
The example below creates a new directory then a Node.js program named _mapsDemo_ using NPM:
61+
62+
```powershell
63+
mkdir mapsDemo
64+
cd mapsDemo
65+
npm init
66+
```
67+
68+
## Create and authenticate a MapsSearchClient
69+
70+
You'll need a `credential` object for authentication when creating the `MapsSearchClient` object used to access the Azure Maps search APIs. You can use either an Azure Active Directory (Azure AD) credential or an Azure subscription key to authenticate. For more information on authentication, see [Authentication with Azure Maps][authentication].
71+
72+
> [!TIP]
73+
> The`MapsSearchClient` is the primary interface for developers using the Azure Maps search library. See [Azure Maps Search client library][JS-SDK] to learn more about the search methods available.
74+
75+
### Using an Azure AD credential
76+
77+
You can authenticate with Azure AD using the [Azure Identity library][Identity library]. To use the [DefaultAzureCredential][defaultazurecredential] provider, you'll need to install the `@azure/identity` package:
78+
79+
```powershell
80+
npm install @azure/identity
81+
```
82+
83+
You'll need to register the new Azure AD application and grant access to Azure Maps by assigning the required role to your service principal. For more information, see [Host a daemon on non-Azure resources][Host daemon]. During this process you'll get an Application (client) ID, a Directory (tenant) ID, and a client secret. Copy these values and store them in a secure place. You'll need them in the following steps.
84+
85+
Set the values of the Application (client) ID, Directory (tenant) ID, and client secret of your Azure AD application, and the map resource’s client ID as environment variables:
86+
87+
| Environment Variable | Description |
88+
|-----------------------|-----------------------------------------------------------------|
89+
| AZURE_CLIENT_ID | Application (client) ID in your registered application |
90+
| AZURE_CLIENT_SECRET | The value of the client secret in your registered application |
91+
| AZURE_TENANT_ID | Directory (tenant) ID in your registered application |
92+
| MAPS_CLIENT_ID | The client ID in your Azure Map account |
93+
94+
You can use a `.env` file for these variables. You'll need to install the [dotenv][dotenv] package:
95+
96+
```powershell
97+
npm install dotenv
98+
```
99+
100+
Next, add a `.env` file in the **mapsDemo** directory and specify these properties:
101+
102+
```text
103+
AZURE_CLIENT_ID="<client-id>"
104+
AZURE_CLIENT_SECRET="<client-secret>"
105+
AZURE_TENANT_ID="<tenant-id>"
106+
MAPS_CLIENT_ID="<maps-client-id>"
107+
```
108+
109+
Once your environment variables are created, you can access them in your JavaScript code:
110+
111+
```JavaScript
112+
const { MapsSearchClient } = require("@azure/maps-search");
113+
const { DefaultAzureCredential } = require("@azure/identity");
114+
require("dotenv").config();
115+
116+
const credential = new DefaultAzureCredential();
117+
const client = new MapsSearchClient(credential, process.env.MAPS_CLIENT_ID);
118+
```
119+
120+
### Using a subscription key credential
121+
122+
You can authenticate with your Azure Maps subscription key. Your subscription key can be found in the **Authentication** section in the Azure Maps account as shown in the following screenshot:
123+
124+
:::image type="content" source="./media/rest-sdk-dev-guides/subscription-key.png" alt-text="A screenshot showing the subscription key in the Authentication section of an Azure Maps account." lightbox="./media/rest-sdk-dev-guides/subscription-key.png":::
125+
126+
You need to pass the subscription key to the `AzureKeyCredential` class provided by the [Azure Maps Search client library for JavaScript/TypeScript][JS-SDK]. For security reasons, it's better to specify the key as an environment variable than to include it in your source code.
127+
128+
You can accomplish this by using a `.env` file to store the subscription key variable. You'll need to install the [dotenv][dotenv] package to retrieve the value:
129+
130+
```powershell
131+
npm install dotenv
132+
```
133+
134+
Next, add a `.env` file in the **mapsDemo** directory and specify the property:
135+
136+
```text
137+
MAPS_SUBSCRIPTION_KEY="<subscription-key>"
138+
```
139+
140+
Once your environment variable is created, you can access it in your JavaScript code:
141+
142+
```JavaScript
143+
const { MapsSearchClient, AzureKeyCredential } = require("@azure/maps-search");
144+
require("dotenv").config();
145+
146+
const credential = new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY);
147+
const client = new MapsSearchClient(credential);
148+
```
149+
150+
## Fuzzy search an entity
151+
152+
The following code snippet demonstrates how, in a simple console application, to import the `azure-maps-search` package and perform a fuzzy search on “Starbucks” near Seattle:
153+
154+
```JavaScript
155+
156+
const { MapsSearchClient, AzureKeyCredential } = require("@azure/maps-search");
157+
require("dotenv").config();
158+
159+
async function main() {
160+
// Authenticate with Azure Map Subscription Key
161+
const credential = new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY);
162+
const client = new MapsSearchClient(credential);
163+
164+
// Setup the fuzzy search query
165+
const response = await client.fuzzySearch({
166+
query: "Starbucks",
167+
coordinates: [47.61010, -122.34255],
168+
countryCodeFilter: ["US"],
169+
});
170+
171+
// Log the result
172+
console.log(`Starbucks search result nearby Seattle:`);
173+
response.results.forEach((result) => {
174+
console.log(`\
175+
* ${result.address.streetNumber} ${result.address.streetName}
176+
${result.address.municipality} ${result.address.countryCode} ${result.address.postalCode}
177+
Coordinate: (${result.position[0].toFixed(4)}, ${result.position[1].toFixed(4)})\
178+
`);
179+
}
180+
181+
main().catch((err) => {
182+
console.error(err);
183+
});
184+
185+
```
186+
187+
In the above code snippet, you create a `MapsSearchClient` object using your Azure credentials. This is done using your Azure Maps subscription key, however you could use the [Azure AD credential](#using-an-azure-ad-credential) discussed in the previous section. You then pass the search query and options to the `fuzzySearch` method. Search for Starbucks (`query: "Starbucks"`) near Seattle (`coordinates: [47.61010, -122.34255], countryFilter: ["US"]`). For more information, see [FuzzySearchRequest][FuzzySearchRequest] in the [Azure Maps Search client library for JavaScript/TypeScript][JS-SDK].
188+
189+
The method `fuzzySearch` provided by `MapsSearchClient` will forward the request to Azure Maps REST endpoints. When the results are returned, they're written to the console. For more information, see [SearchAddressResult][SearchAddressResult].
190+
191+
Run `search.js` with Node.js:
192+
193+
```powershell
194+
node search.js
195+
```
196+
197+
## Search an Address
198+
199+
The [searchAddress][searchAddress] method can be used to get the coordinates of an address. Modify the `search.js` from the sample as follows:
200+
201+
```JavaScript
202+
const { MapsSearchClient, AzureKeyCredential } = require("@azure/maps-search");
203+
require("dotenv").config();
204+
205+
async function main() {
206+
const credential = new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY);
207+
const client = new MapsSearchClient(credential);
208+
209+
const response = await client.searchAddress(
210+
"1912 Pike Pl, Seattle, WA 98101, US"
211+
);
212+
213+
console.log(`The coordinate is: ${response.results[0].position}`);}
214+
215+
main().catch((err) => {
216+
console.error(err);
217+
});
218+
```
219+
220+
The results returned from `client.searchAddress` are ordered by confidence score and in this example only the first result returned with be displayed to the screen.
221+
222+
## Batch reverse search
223+
224+
Azure Maps Search also provides some batch query methods. These methods will return Long Running Operations (LRO) objects. The requests might not return all the results immediately, so you can wait until completion or query the result periodically. The example below demonstrates how to call batched reverse search method:
225+
226+
```JavaScript
227+
const poller = await client.beginReverseSearchAddressBatch([
228+
// This is an invalid query
229+
{ coordinates: [148.858561, 2.294911] },
230+
{
231+
coordinates: [47.61010, -122.34255],
232+
},
233+
{ coordinates: [47.6155, -122.33817] },
234+
options: { radiusInMeters: 5000 },
235+
]);
236+
```
237+
238+
In this example, three queries are passed into the _batched reverse search_ request. The first query is invalid, see [Handing failed requests](#handing-failed-requests) for an example showing how to handle the invalid query.
239+
240+
Use the `getResult` method from the poller to check the current result. You check the status using `getOperationState` to see if the poller is still running. If it is, you can keep calling `poll` until the operation is finished:
241+
242+
```JavaScript
243+
while (poller.getOperationState().status === "running") {
244+
const partialResponse = poller.getResult();
245+
logResponse(partialResponse)
246+
await poller.poll();
247+
}
248+
```
249+
250+
Alternatively, you can wait until the operation has completed, by using `pollUntilDone()`:
251+
252+
```JavaScript
253+
const response = await poller.pollUntilDone();
254+
logResponse(response)
255+
```
256+
257+
A common scenario for LRO is to resume a previous operation later. Do that by serializing the poller’s state with the `toString` method, and rehydrating the state with a new poller using `resumeReverseSearchAddressBatch`:
258+
259+
```JavaScript
260+
const serializedState = poller.toString();
261+
const rehydratedPoller = await client.resumeReverseSearchAddressBatch(
262+
serializedState
263+
);
264+
const response = await rehydratedPoller.pollUntilDone();
265+
logResponse(response);
266+
```
267+
268+
Once you get the response, you can log it:
269+
270+
```JavaScript
271+
function logResponse(response) {
272+
console.log(
273+
`${response.totalSuccessfulRequests}/${response.totalRequests} succeed.`
274+
);
275+
response.batchItems.forEach((item, idx) => {
276+
console.log(`The result for ${idx + 1}th request:`);
277+
// Check if the request is failed
278+
if (item.response.error) {
279+
console.error(item.response.error);
280+
} else {
281+
item.response.results.forEach((result) => {
282+
console.log(result.address.freeformAddress);
283+
});
284+
}
285+
});
286+
}
287+
```
288+
289+
### Handing failed requests
290+
291+
Handle failed requests by checking for the `error` property in the response batch item. See the `logResponse` function in the completed batch reverse search example below.
292+
293+
### Completed batch reverse search example
294+
295+
The complete code for the reverse address batch search example:
296+
297+
```JavaScript
298+
const { MapsSearchClient, AzureKeyCredential } = require("@azure/maps-search");
299+
require("dotenv").config();
300+
301+
async function main() {
302+
const credential = new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY);
303+
const client = new MapsSearchClient(credential);
304+
305+
const poller = await client.beginReverseSearchAddressBatch([
306+
// This is an invalid query
307+
{ coordinates: [148.858561, 2.294911] },
308+
{
309+
coordinates: [47.61010, -122.34255],
310+
},
311+
{ coordinates: [47.6155, -122.33817] },
312+
options: { radiusInMeters: 5000 },
313+
]);
314+
315+
// Get the partial result and keep polling
316+
while (poller.getOperationState().status === "running") {
317+
const partialResponse = poller.getResult();
318+
logResponse(partialResponse);
319+
await poller.poll();
320+
}
321+
322+
// You can simply wait for the operation is done
323+
// const response = await poller.pollUntilDone();
324+
// logResponse(response)
325+
326+
// Resume the poller
327+
const serializedState = poller.toString();
328+
const rehydratedPoller = await client.resumeReverseSearchAddressBatch(
329+
serializedState
330+
);
331+
const response = await rehydratedPoller.pollUntilDone();
332+
logResponse(response);
333+
}
334+
335+
function logResponse(response) {
336+
console.log(
337+
`${response.totalSuccessfulRequests}/${response.totalRequests} succeed.`
338+
);
339+
response.batchItems.forEach((item, idx) => {
340+
console.log(`The result for ${idx + 1}th request:`);
341+
if (item.response.error) {
342+
console.error(item.response.error);
343+
} else {
344+
item.response.results.forEach((result) => {
345+
console.log(result.address.freeformAddress);
346+
});
347+
}
348+
});
349+
}
350+
351+
main().catch((err) => {
352+
console.error(err);
353+
});
354+
```
355+
356+
## Additional information
357+
358+
- The [Azure Maps Search client library for JavaScript/TypeScript][JS-SDK].
359+
360+
[JS-SDK]: /javascript/api/overview/azure/maps-search-readme?view=azure-node-preview
361+
362+
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-js/tree/@azure/maps-search_1.0.0-beta.1/sdk/identity/identity#defaultazurecredential
363+
364+
[searchAddress]: /javascript/api/@azure/maps-search/mapssearchclient?view=azure-node-preview#@azure-maps-search-mapssearchclient-searchaddress
365+
366+
[FuzzySearchRequest]: /javascript/api/@azure/maps-search/fuzzysearchrequest?view=azure-node-preview
367+
368+
[SearchAddressResult]: /javascript/api/@azure/maps-search/searchaddressresult?view=azure-node-preview
369+
370+
[search]: /rest/api/maps/search
371+
[Node.js Release]: https://github.com/nodejs/release#release-schedule
372+
[Node.js]: https://nodejs.org/en/download/
373+
[Azure Maps account]: quick-demo-map-app.md#create-an-azure-maps-account
374+
[Subscription key]: quick-demo-map-app.md#get-the-primary-key-for-your-account
375+
376+
[authentication]: azure-maps-authentication.md
377+
[Identity library]: /javascript/api/overview/azure/identity-readme
378+
379+
[Host daemon]: /azure/azure-maps/how-to-secure-daemon-app#host-a-daemon-on-non-azure-resources
380+
[dotenv]: https://github.com/motdotla/dotenv#readme
381+
382+
[search package]: https://www.npmjs.com/package/@azure/maps-search
383+
[search readme]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/maps/maps-search/README.md
384+
[search sample]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/maps/maps-search/samples/v1-beta
385+
386+
[js route readme]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/maps/maps-route-rest/README.md
387+
[js route package]: https://www.npmjs.com/package/@azure-rest/maps-route
388+
[js route sample]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/maps/maps-route-rest/samples/v1-beta
72 KB
Loading

0 commit comments

Comments
 (0)