Как я могу использовать отложенный объект для получения долготы и широты с помощью API геолокации HTML5?

Я хотел бы использовать HTML5 GeoLocation API для получения моей долготы и широты и управления запросом с помощью объекта jQuery Deferred.

Вот как выглядит мой код:

var geoLocation = {

    getLocation: function() {

        // create deferred object
        var deferred = $.Deferred();

        // if geo location is supported
        if(navigator.geolocation) {

            // get current position and pass the results to this.geoLocationSuccess or time out after 5 seconds if it fails
            navigator.geolocation.getCurrentPosition(this.geoLocationSuccess, this.geoLocationError, {
                timeout: 5000
            });

        } else {

            // geo location isn't supported
            console.log('Your browser does not support Geo Location.');
        }

    },

    geoLocationSuccess: function(position) {

        // resolve deffered object
        deferred.resolve(position.coords.latitude, position.coords.longitude);

        // return promise
        return deferred.promise();
    },

    geoLocationError: function() {
        console.log('Geo Location failed.');
    }

};

А вот мой отложенный объект:

$.when(geoLocation.getLocation()).then(function(data, textStatus, jqXHR) {

    console.log(data);

});

Я ожидаю, что долгота и широта будут возвращены обратным вызовом then(), но вместо этого я получаю сообщение об ошибке, что deferred не определено. Я думаю, что это как-то связано с областью, в которой я определяю свой отложенный объект, но я не уверен. Что мне не хватает?


person Michael Lynch    schedule 21.09.2014    source источник


Ответы (2)


Майкл, после прочтения ответа Hackaholic и вашего собственного, оба будут работать в отношении обработки успешно возвращенных данных, но ошибки можно было бы лучше обрабатывать.

В случае сбоя navigator.geolocation.getCurrentPosition() будет передана потенциально информативная ошибка PositionError. возразить своему обработчику ошибок. Этот объект, который можно передать по цепочке обещаний и обработать в вызывающей функции, игнорируется в обоих ответах.

Точно так же отказ от обещания также может быть использован для передачи вашей собственной ошибки «Ваш браузер не поддерживает геолокацию» по цепочке обещаний.

var geoLocation = {
    getLocation: function() {
        var deferred = $.Deferred();
        if(navigator.geolocation) {
            // geo location is supported. Call navigator.geolocation.getCurrentPosition and :
            // - resolve the promise with the returned Position object, or
            // - reject the promise with the returned PositionError object, or
            // - time out after 5 seconds
            navigator.geolocation.getCurrentPosition(deferred.resolve, deferred.reject, { timeout: 5000 });
        } else {
            //geo location isn't supported
            //Reject the promise with a suitable error message
            deferred.reject(new Error('Your browser does not support Geo Location.'));
        }
        return deferred.promise();
    } 
};

Не обращая внимания на комментарии, это очень компактно и обратите внимание, как geoLocation.getLocation() не пытается обрабатывать ошибки, но делает их доступными для обработчика ошибок вызывающей функции.

Теперь $.when() не нужен, потому что ваша функция geoLocation.getLocation() возвращает промис, который имеет свой собственный метод .then(). Это уже "потом" без $.when().

geoLocation.getLocation().then(function(position) {
    console.dir(position);
}).fail(function(err) {
    console.error(err);
});

Таким образом, вы полностью используете способность промиса обрабатывать успех или неудачу.

person Roamer-1888    schedule 22.09.2014
comment
Спасибо, что нашли время, чтобы предоставить этот ответ, потому что вы абсолютно правы в том, что ошибки должны обрабатываться лучше. Я обновлю свой код. - person Michael Lynch; 22.09.2014

Я понял это, но на самом деле я должен указать Скотта Аллена на Ода коду.

Функции, которые ожидает разрешения $.when(), должны возвращать promise() напрямую.

В моем случае я разрешал отложенный объект и возвращал promise() в функции обратного вызова getCurrentLocation(), а не функцию, указанную в $.when().

РЕШЕНИЕ:

var geoLocation = {

    getLocation: function() {

        var deferred = $.Deferred();

        // if geo location is supported
        if(navigator.geolocation) {

            // get current position and pass the results to getPostalCode or time out after 5 seconds if it fails
            navigator.geolocation.getCurrentPosition(deferred.resolve, this.geoLocationError, {
                timeout: 5000
            });

        } else {

            //geo location isn't supported
            console.log('Your browser does not support Geo Location.');
        }

        return deferred.promise();

    },

    geoLocationError: function() {
        console.log('Geo Location failed.');
    }

};

$.when(geoLocation.getLocation()).then(function(data, textStatus, jqXHR) {

    console.log(data.coords.longitude, data.coords.latitude);

});
person Michael Lynch    schedule 21.09.2014