REST API
JavaScript
Как использовать API платформы Naviaddress
из языка программирования JavaScript?
TD;LR

Если кратко, то для использования Naviadress API нужно выполнить несложный GET или POST запрос с заданными параметрами. Например, получить информацию о заданном объекте можно с помощью вот такой вот коротенькой программы:
let container = '7'; // Это адресный контейнер. 7 - это Россия. 
let naviaddress = '0022'; // Это адрес. [7]0022 - адрес российского офиса Naviaddress
let url = 'https://staging-api.naviaddress.com/api/v1.5/Addresses/'
	+ container+'/' + naviaddress;

fetch(url).then((res1)=> 
	res1.json().then((res2)=>{
		console.log(res2.result);
	});
);
Пример программы

Теперь давайте напишем небольшое приложение, которое будет определять навиадрес, ближайший к месту вашего нахождения.

Для этого давайте определим последовательность действий:

  1. Сначала получим текущие координаты ноутбука или телефона, на котором будет выполняться программа с помощью Geolocation API, встроенного в любой современный браузер. Система должна у пользователя запросить разрешение на доступ к этой полезной информации.
  2. Создадим вокруг полученных координат небольшой квадрат из четырех точек, отстоящих на расстояние на одну тысячную градуса от полученной точки (это значение запишем заранее в константу DELTA).
  3. Получим список всех навиадресов, находящихся внутри заданного квадрата. Ограничим количество выдаваемых навиадресов с помощью константы LIMIT.
  4. С помощью расчета евклидового расстояния для каждой точки найдем ближайшие навиадрес к нашему местоположению.
  5. И, наконец, получим данные из ближайшего навиадреса.

Так как обращения к REST API будут асинхронными, то воспользуемся новыми операторами JavaScript async/await и обернем их в асинхронную функцию main(). В принципе, никто не мешает нам сделать то же самое с помощью традиционных callback-вызовов.
main();

async function main() {
	let coords = await getLocation();
	let rect = createRect(coords,DELTA);
	let list = await getList(rect);
	let nearestAddr = findNearestAddress(coords, list);
	let address = await getAddress(nearestAddr);
	showResults(coords, list, address);
}
Зададим константы:
  • DELTA - задает размер квадрата вокруг заданной точки.
  • LIMIT - ограничивает количество адресов, выданных с помощью функции Map
const DELTA = 0.001; // Граница выбора объектов (в градусах)
const LIMIT = 100;   // Ограничение на количество возвращаемых объектов
getLocation()

Текущее местоположения мы получим с помощью встроенной функции браузера из Geolocation API navigator.geolocation.getCurrentPosition(), которая в качестве параметра принимает callback-функцию - обработчик полученных координат.
function getLocation() {
	return new Promise((resolve,reject) => {
	    if (navigator.geolocation) {
	        navigator.geolocation.getCurrentPosition(
	        	(position)=>resolve(position.coords));
	    } else {
	    	alert("Геолокация не поддерживается вашим браузером");
	    	reject();
	    }
	});
}
createRect()

Так как искать навиадреса мы будем вокруг нашего местоположения, то давайте создадим квадрат, расположенный на расстоянии delta по горизонтали и вертикали от наших координат.
function createRect(coords,delta) {
	return {
		lt_lat:coords.latitude - delta,
		lt_lng:coords.longitude - delta,
		rb_lat:coords.latitude + delta,
		rb_lng:coords.longitude + delta
	}
}
getList()

Теперь нужно получить список объектов, находящихся в заданном квадрате. Это можно сделать с помощью метода Map, в параметрах которого необходимо указать координаты двух угловых точек (левой верхней и правой нижней), а также ограничение на вывод за один раз. Надо добавить, что эта функция поддерживает пагинацию (которая, правда, в этом примере не используется).
function getList(rect) {
	return new Promise((resolve, reject) => {
		let url = new URL('https://staging-api.naviaddress.com/api/v1.5/Map');
		let params = {
			address_type: 'free',
			limit: LIMIT,
			lt_lat:rect.lt_lat, 
			lt_lng:rect.lt_lng,
			rb_lat:rect.rb_lat, 
			rb_lng:rect.rb_lng
		};
		url.search = new URLSearchParams(params);

		fetch(url).then((res1)=>
			res1.json().then((res2)=>resolve(res2.result))
		);
	});
}
findNearestAddress()

Полученный массив мы сортируем используя простейшую формулу Евклидова расстояния. Самый близкий объект в массиве - и есть искомый адрес.
function findNearestAddress(coords, list) {
	list.sort((a,b)=>distance(a)-distance(b));
	return list[0];

	function distance(el){
		return Math.sqrt(Math.pow(el.point.lat - coords.latitude,2) 
				+ Math.pow(el.point.lng - coords.longitude,2));
	}
}
getAddress()

Нам осталось лишь получить данные из карточки навиадреса, которые доступны при помощи простого GET-запроса с указанием контейнера (кода страны) и самого адреса в URL.
function getAddress(obj) {
	return new Promise((resolve, reject) => {
		let url = 'https://staging-api.naviaddress.com/api/v1.5/Addresses/'
			+ obj.container+'/'+obj.naviaddress;

		fetch(url).then((res1)=>
			res1.json().then((res2)=>resolve(res2.result))
		);
	});
}
Вместо завершения - Как пройти авторизацию?
getToken()


Хотя для вышеприведенной задачи получения навиадресов с сервера авторизация не нужна, но для ряда задач она является обязательной. Давайте посмотрим, как она реализуется силами JavaScript. Приведенная ниже функция getToken() возвращает токен авторизации (точнее промис, который в свою очередь возвращает токен), который уже потом можно использовать в других запросах к серверу через Naviaddress API.

Для доступа к закрытым функциям API обязательно наличие ключа, который можно получить заполнив специальную регистрационную форму.
function getToken() {
	return new Promise((resolve,reject) => {
		let url = 'https://staging-api.naviaddress.com/api/v1.5/Sessions';
		let params = {
			password:'123456',    // Пароль и логин для доступа к API 
			Email:'abc@def.com'  //  нужно получить заполнив форму регистрации
		};

		fetch(url,
		{
		    headers: {
		      'Accept': 'application/json',
		      'Content-Type': 'application/json'
		    },
		    method: "POST",
		    body: JSON.stringify(params)
		})
		.then((res1) => 
			res1.json().then((res2) => {
				resolve(res2.token);
			});
		);
	});
}
Получить с помощью этой функции токен можно так, как приведено на примере ниже:
getToken().then((token) => {
     // Здесь можно вызывать специальные функции Naviaddress API
     console.log(token)
});
Полный текст приведенной выше программы можно посмотреть на специальной странице в GIST по ссылке.

Сохраните файл с программой в файл index.html. Этот файл нужно запустить через любой веб-сервер (а не напрямую открыть файл с диска из браузера).

Например, Вы можете установить и запустить пакет http-server, которые работает поверх NodeJS. Для его запуска установить NodeJS (если она еще не установлена у вас на компьютере) с официального сайта https://nodejs.org/

П
осле этого установите глобально и запустить HTTP-сервер из каталога с файлом index.html.
> npm install -g http-server
> http-server
Вам остается только открыть в браузере локальный сервер, введя в адресную строку ссылку: http://localhost:8080

Дополнение

В некоторых случаях программа выдает ошибку, если рядом с вашим местоположением нет никаких навиадресов. Для того, чтобы избавиться от этой ошибки увеличьте значение параметра DELTA в несколько раз, чтобы гарантированно "захватить" какие-нибудь навиадреса.


Автор: А.Гершун (10.09.2018)
Made on
Tilda