Задать вопрос

Асинхронный расчет маршрутов при помощи API Yandex Map (deferred.promise)?

Пытаюсь упрощенно решить задачу коммивояжёра.
Для этого считаю расстояния от начальной (корневой) точки (myPointRoot) до других (элементы массива myPoints)

Суть задачи:
На входе есть точка myPointRoot и массив точек myPoints
На выходе нужен массив myLenghts с расстоями до них

Для рассчета расстояния используется route из Yandex Map API - api.yandex.ru/maps/doc/jsapi/2.0/dg/concepts/router.xml
Но, эта штука асихронная.

Далее идет моё решение, которое не работает и вполне возможно что это вообще совсем неправильно:

Так как route() - асинхронная функция, маршруты могут рассчитаться в любом порядке и неизвестно когда рассчитаются.
Поэтому нужен массив promise-объектов (я использую их из JQuery) - promiseArray. В цикле мы его заполняем, и когда каждый маршрут рассчитается, он для своего promise выполнит .resolve()
А сразу после цикла, вешаем обработку при помощи JQuery.when() которая выполнится только тогда когда все маршруты в массиве promiseArray изменят свой статус на "resolve".
Вообще-то, сама функция route возвращает promise-объект и его самого можно засунуть в массив promiseArray. Но он, какой-то свой, яндексовский и я не смог написать обработчик, который сработает когда все элементы promiseArray выполнятся.

Вот тут весь код (можно поиграться) - jsfiddle.net/4xfxR/1

Вот кусок:
// запускаемся только после загрузки yandex.api
    ymaps.ready(init);
    
    var promiseArray = []; // массив обещаний
    var myRootPoint = [52.290139, 104.279331]; //начальная точка
    var myPoints = [
	[52.284889, 104.282771],
	[52.283527180127, 104.26076298926],
	[52.263199, 104.19824]
	
    ];

    function init() { 
	for(var i = 0; i<myPoints.length; i++) {
	    var coor = [myRootPoint, myPoints[i]];
	    // пришлось делать замыкание
	    // потому что иначе i не запоминается
	    var fn = (function() {
		var dfd = new $.Deferred();
		promiseArray.push(dfd.promise());

		var myI = i; // сохраняем в замыкании ID элемента
		var myCoor = coor; // сохраняем в замыкании координаты
		ymaps.route(myCoor).then(
		    function (route) {
			writeText('маршрут='+myI+" расстояние=" +route.getLength());
			// "завершаем" promise-object
			promiseArray[myI].resolve();
		    },
		    function (error) {
			promiseArray[myI].reject();
			writeText('Возникла ошибка: ' + error.message);
		    }
		); //end ymaps.route
	    }); //end fn
	    fn(); // выполняем "замыкание"
	} //end for

	$.when.apply($, promiseArray).then(function(){
	    // не срабатывает этот кусок 
	    console.log(promiseArray);
	    writeText('Всё обработано!');
	});
    } //end init



Вопрос: правильно ли я делаю?
Если да, то почему не выводится сообщение "Всё обработано", а если нет - как делать нужно?
  • Вопрос задан
  • 5335 просмотров
Подписаться 5 Оценить Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы