JavaScript/TypeScript REST SDK 開發人員指南 (預覽)
Azure 地圖服務 JavaScript/TypeScript REST SDK (JavaScript SDK) 支援使用 Azure 地圖服務的搜尋服務進行搜尋,像是地址搜尋、城市或國家的界限搜尋,以及依座標搜尋。 本文可協助您開始建置包含 Azure 地圖服務功能的位置感知應用程式。
注意
Azure 地圖服務 JavaScript SDK 支援 LTS 版本的 Node.js。 如需詳細資訊,請參閱 Node.js 發行工作群組。
必要條件
- Azure 地圖服務帳戶。
- 訂用帳戶金鑰或其他形式的 Azure 地圖服務驗證。
- Node.js。
提示
您可以透過程式設計方式建立 Azure 地圖服務帳戶,以下是使用 Azure CLI 的範例:
az maps account create --kind "Gen2" --account-name "myMapAccountName" --resource-group "<resource group>" --sku "G2"
建立 Node.js 專案
下列範例會建立新的目錄,然後使用 npm 建立名為 mapsDemo 的 Node.js 程式:
mkdir mapsDemo
cd mapsDemo
npm init
安裝搜尋套件
您必須安裝搜尋套件,才能使用 Azure 地圖服務 JavaScript SDK。 每個 Azure 地圖服務,包括搜尋、路線規劃、呈現和地理位置,各自位於本身的套件中。
npm install @azure-rest/maps-search
安裝套件之後,請在 mapsDemo
目錄中建立 search.js
檔案:
mapsDemo
+-- package.json
+-- package-lock.json
+-- node_modules/
+-- search.js
Azure 地圖服務
服務名稱 | npm 套件 | 範例 |
---|---|---|
Search | @azure-rest/maps-search | 搜尋樣本 (英文) |
路由 | @azure-rest/maps-route (英文) | 路由樣本 (英文) |
轉譯 | @azure-rest/maps-render | 轉譯樣本 (英文) |
地理位置 | @azure-rest/maps-geolocation | 地理位置樣本 (英文) |
建立及驗證 MapsSearchClient
建立用以存取 Azure 地圖服務搜尋 API 的 MapsSearchClient
物件時,您需要 credential
物件以供驗證。 您可以使用 Microsoft Entra 認證或 Azure 訂用帳戶金鑰進行驗證。 如需關於驗證的詳細資訊,請參閱驗證 Azure 地圖服務。
提示
MapsSearchClient
是開發人員使用 Azure 地圖服務搜尋程式庫的主要介面。 若要深入了解可用的搜尋方法,請參閱 Azure 地圖服務搜尋用戶端程式庫。
使用 Microsoft Entra 認證
您可以使用 Azure 身分識別程式庫向 Microsoft Entra ID 進行驗證。 若要使用 DefaultAzureCredential 提供者,您必須安裝 @azure/identity
套件:
npm install @azure/identity
您必須註冊新的 Microsoft Entra 應用程式,並將所需的角色指派給服務主體,以授與對 Azure 地圖服務的存取權。 如需詳細資訊,請參閱在非 Azure 資源上裝載精靈。 系統會傳回應用程式 (用戶端) 識別碼、目錄 (租用戶) 識別碼,以及用戶端密碼。 複製這些值,並將其儲存在安全的地方。 在下列步驟中,您會需要用到這些資料。
將應用程式 (用戶端) 識別碼、目錄 (租用戶) 識別碼和 Microsoft Entra 應用程式用戶端密碼的值,以及地圖資源的用戶端識別碼的值設定為環境變數:
環境變數 | 描述 |
---|---|
AZURE_CLIENT_ID | 已註冊應用程式中的應用程式 (用戶端) 識別碼 |
AZURE_CLIENT_SECRET | 已註冊應用程式中用戶端密碼的值 |
AZURE_TENANT_ID | 已註冊應用程式中的目錄 (租用戶) 識別碼 |
MAPS_CLIENT_ID | Azure 地圖服務帳戶中的用戶端識別碼 |
您可以使用 .env
檔案取得這些變數。 您必須安裝 dotenv 套件:
npm install dotenv
接下來,在 mapsDemo 目錄中新增 .env
檔案,並指定下列屬性:
AZURE_CLIENT_ID="<client-id>"
AZURE_CLIENT_SECRET="<client-secret>"
AZURE_TENANT_ID="<tenant-id>"
MAPS_CLIENT_ID="<maps-client-id>"
建立環境變數之後,您就可以使用 JavaScript 程式碼存取這些變數:
const MapsSearch = require("@azure-rest/maps-search").default;
const { DefaultAzureCredential } = require("@azure/identity");
require("dotenv").config();
const credential = new DefaultAzureCredential();
const client = MapsSearch(credential, process.env.MAPS_CLIENT_ID);
使用訂用帳戶金鑰認證
您可以使用 Azure 地圖服務訂用帳戶金鑰進行驗證。 您可以在 Azure 地圖服務帳戶的 [驗證] 區段中找到您的訂用帳戶金鑰,如下列螢幕擷取畫面所示:
您必須將訂用帳戶金鑰傳遞至 Azure Core Authentication Package 所提供的 AzureKeyCredential
類別。 基於安全性考慮,最好將金鑰指定為環境變數,而不是包含在原始程式碼中。
使用 .env
檔案來儲存訂用帳戶金鑰變數以達成此目的。 您必須安裝 dotenv 套件才能擷取以下的值:
npm install dotenv
接下來,在 mapsDemo 目錄中新增 .env
檔案,並指定以下屬性:
MAPS_SUBSCRIPTION_KEY="<subscription-key>"
建立環境變數之後,您就可以使用 JavaScript 程式碼存取它:
const MapsSearch = require("@azure-rest/maps-search").default;
const { AzureKeyCredential } = require("@azure/core-auth");
require("dotenv").config();
const credential = new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY);
const client = MapsSearch(credential);
使用共用存取簽章 (SAS) 權杖認證
共用存取簽章 (SAS) 權杖是使用 JSON Web 權杖 (JWT) 格式建立的驗證權杖,並以密碼編譯方式簽署,以向 Azure 地圖服務 REST API 證明應用程式的驗證。
您可以使用 AzureMapsManagementClient.accounts.listSas
套件來取得 SAS 權杖。 請遵循建立和驗證 AzureMapsManagementClient
一節,先進行設定。
其次,遵循 Azure 地圖服務的受控識別,為您的 Azure 地圖服務帳戶建立受控識別。 複製受控識別的主體識別碼 (物件識別碼)。
接下來,安裝 Azure Core Authentication Package 套件以使用 AzureSASCredential
:
npm install @azure/core-auth
最後,您可使用 SAS 權杖來驗證用戶端:
const MapsSearch = require("@azure-rest/maps-search").default;
const { AzureSASCredential } = require("@azure/core-auth");
const { DefaultAzureCredential } = require("@azure/identity");
const { AzureMapsManagementClient } = require("@azure/arm-maps");
const subscriptionId = "<subscription ID of the map account>"
const resourceGroupName = "<resource group name of the map account>";
const accountName = "<name of the map account>";
const mapsAccountSasParameters = {
start: "<start time in ISO format>", // e.g. "2023-11-24T03:51:53.161Z"
expiry: "<expiry time in ISO format>", // maximum value to start + 1 day
maxRatePerSecond: 500,
principalId: "<principle ID (object ID) of the managed identity>",
signingKey: "primaryKey",
};
const credential = new DefaultAzureCredential();
const managementClient = new AzureMapsManagementClient(credential, subscriptionId);
const {accountSasToken} = await managementClient.accounts.listSas(
resourceGroupName,
accountName,
mapsAccountSasParameters
);
if (accountSasToken === undefined) {
throw new Error("No accountSasToken was found for the Maps Account.");
}
const sasCredential = new AzureSASCredential(accountSasToken);
const client = MapsSearch(sasCredential);
地理編碼
下列程式碼片段示範如何在簡單的主控台應用程式中匯入 @azure-rest/maps-search
套件,並使用 GetGeocoding 查詢來取得地址的座標:
const MapsSearch = require("@azure-rest/maps-search").default;
const { isUnexpected } = require("@azure-rest/maps-search");
const { AzureKeyCredential } = require("@azure/core-auth");
require("dotenv").config();
async function main() {
const credential = new AzureKeyCredential(
process.env. MAPS_SUBSCRIPTION_KEY
);
const client = MapsSearch(credential);
const response = await client.path("/geocode", "json").get({
queryParameters: {
query: "1301 Alaskan Way, Seattle, WA 98101, US",
},
});
if (isUnexpected(response)) {
throw response.body.error;
}
const [ lon, lat ] = response.body.features[0].geometry.coordinates;
console.log(`The coordinate is: (${lat}, ${lon})`);
}
main().catch((err) => {
console.error(err);
});
此程式碼片段示範如何使用 Azure 地圖服務搜尋用戶端程式庫中的 MapsSearch
方法,建立具有 Azure 認證的 client
物件。 您可以使用 Azure 地圖服務訂用帳戶金鑰或 Microsoft Entra 認證。 path
參數會指定 API 端點,在此案例中為 "/geocode"。 get
方法會使用查詢參數傳送 HTTP GET 要求。 此查詢會搜尋 "1301 Alaskan Way, Seattle, WA 98101, US" 的座標。 SDK 會將結果傳回為 GeocodingResponseOutput 物件,並將其寫入主控台。 結果會依此範例中的信賴分數排序,而且只會將第一筆結果顯示到畫面。 如需詳細資訊,請參閱 GetGeocoding。
使用 Node.js 執行 search.js
:
node search.js
批次反向地理編碼
Azure 地圖服務搜尋也會提供一些批次查詢方法。 下列範例示範如何呼叫批次反向搜尋方法:
const batchItems = [
// This is an invalid query
{ coordinates: [2.294911, 148.858561] },
{
coordinates: [-122.34255, 47.6101],
},
{ coordinates: [-122.33817, 47.6155] },
];
const response = await client.path("/reverseGeocode:batch").post({
body: { batchItems },
});
在此範例中,要求本文的 batchItems
中包含三個座標。 第一個項目無效,如需如何處理無效項目的範例,請參閱處理失敗的要求。
取得回應之後,即可予以記錄:
function logResponseBody(resBody) {
const { summary, batchItems } = resBody;
const { totalRequests, successfulRequests } = summary;
console.log(`${successfulRequests} out of ${totalRequests} requests are successful.`);
batchItems.forEach(({ response }, idx) => {
if (response.error) {
console.log(`Error in ${idx + 1} request: ${response.error.message}`);
} else {
console.log(`Results in ${idx + 1} request:`);
response.features.forEach((feature) => {
console.log(` ${feature.properties.address.freeformAddress}`);
});
}
});
}
處理失敗的要求
檢查回應批次項目中是否有 error
屬性,以處理失敗的要求。 請參閱下列已完成之批次反向搜尋範例中的 logResponseBody
函式。
已完成的批次反向搜尋範例
反向地址批次搜尋範例的完整程式碼:
const MapsSearch = require("@azure-rest/maps-search").default,
{ isUnexpected } = require("@azure-rest/maps-search");
const { AzureKeyCredential } = require("@azure/core-auth");
require("dotenv").config();
async function main() {
const credential = new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY);
const client = MapsSearch(credential);
const batchItems = [
// This is an invalid query
{ coordinates: [2.294911, 148.858561] },
{
coordinates: [-122.34255, 47.6101],
},
{ coordinates: [-122.33817, 47.6155] },
];
const response = await client.path("/reverseGeocode:batch").post({
body: { batchItems },
});
if (isUnexpected(response)) {
throw response.body.error;
}
logResponseBody(resumeResponse.body);
}
function logResponseBody(resBody) {
const { summary, batchItems } = resBody;
const { totalRequests, successfulRequests } = summary;
console.log(`${successfulRequests} out of ${totalRequests} requests are successful.`);
batchItems.forEach(({ response }, idx) => {
if (response.error) {
console.log(`Error in ${idx + 1} request: ${response.error.message}`);
} else {
console.log(`Results in ${idx + 1} request:`);
response.features.forEach((feature) => {
console.log(` ${feature.properties.address.freeformAddress}`);
});
}
});
}
main().catch(console.error);
使用 V1 SDK
我們正努力讓所有 V1 功能都可在 V2 中使用,在此之前,請視需要安裝下列 V1 SDK 套件:
npm install @azure-rest/map-search-v1@npm:@azure-rest/map-search@^1.0.0
npm install @azure-rest/map-search-v2@npm:@azure-rest/map-search@^2.0.0
然後,您可以匯入這兩個套件:
const MapsSearchV1 = require("@azure-rest/map-search-v1").default;
const MapsSearchV2 = require("@azure-rest/map-search-v2").default;
下列範例示範如何建立函式,以接受地址及搜尋其周圍的 POI。 使用 V2 SDK 來取得位置的座標 (/geocode),以及使用 V1 SDK 來搜尋其周圍的 POI (/search/nearby)。
const MapsSearchV1 = require("@azure-rest/map-search-v1").default;
const MapsSearchV2 = require("@azure-rest/map-search-v2").default;
const { AzureKeyCredential } = require("@azure/core-auth");
const { isUnexpected: isUnexpectedV1 } = require("@azure-rest/maps-search-v1");
const { isUnexpected: isUnexpectedV2 } = require("@azure-rest/maps-search-v2");
require("dotenv").config();
/** Initialize the MapsSearchClient */
const clientV1 = MapsSearchV1(new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY));
const clientV2 = MapsSearchV2(new AzureKeyCredential(process.env.MAPS_SUBSCRIPTION_KEY));
async function searchNearby(address) {
/** Make a request to the geocoding API */
const geocodeResponse = await clientV2
.path("/geocode")
.get({ queryParameters: { query: address } });
/** Handle error response */
if (isUnexpectedV2(geocodeResponse)) {
throw geocodeResponse.body.error;
}
const [lon, lat] = geocodeResponse.body.features[0].geometry.coordinates;
/** Make a request to the search nearby API */
const nearByResponse = await clientV1.path("/search/nearby/{format}", "json").get({
queryParameters: { lat, lon },
});
/** Handle error response */
if (isUnexpectedV1(nearByResponse)) {
throw nearByResponse.body.error;
}
/** Log response body */
for(const results of nearByResponse.body.results) {
console.log(
`${result.poi ? result.poi.name + ":" : ""} ${result.address.freeformAddress}. (${
result.position.lat
}, ${result.position.lon})\n`
);
}
}
async function main(){
searchNearBy("15127 NE 24th Street, Redmond, WA 98052");
}
main().catch((err) => {
console.log(err);
})