简体   繁体   中英

How to implement promises with the HTML5 Geolocation API?

How could I correct the code below so that it does not return the undefined value for the getPreciseLocation function?

In summary, there should be an AJAX call to get the current weather when the user clicks the #precise-location-prompt and shares the location with the browser. However at the moment there is an undefined value error straight after the user clicks on the #precise-location-prompt .

// Get weather data for the current location
function getCurrentWeather(coordinates) {
  return $.ajax('http://www.example.com/lat=' + coordinates[0] + '&lon=' + coordinates[1]);
}

// Show weather in DOM
function showCurrentWeather(data) {
  var currentTemperature = data.temperature;
  $('#current-temperature').text(currentTemperature);
}

// Get precise location based via the Geolocation API
function getPreciseLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(displayPosition, displayError);
  } else {
    console.log("Geolocation is not supported by this browser");
  }
}

// Success function for the Geolocation API
function displayPosition(position) {
  return [position.coords.latitude, position.coords.longitude];
}

// Error function for the Geolocation API
function displayError(error) {
  console.log('Precise location is not available at the moment.');
}

// Promises chain with the AJAX requests
function getWeatherWrapper() {
  return getPreciseLocation().then(function(locationData) {
    return getCurrentWeather(locationData);
    }).then(function(weatherData) {
      return showCurrentWeather(weatherData);
    });
}

// User's interaction with the website
$('#precise-location-prompt').on('click', getWeatherWrapper);

This demo uses the JSfiddle AJAX methods (which, strangely, uses Mootools) to mock the request but you can substitute in the $.ajax method. I also substituted the rest of the jQuery for vanilla JS event listeners and selectors for this test, but you can add them back in for your code very easily.

Return a new promise which resolves in the success callback.

function getCurrentWeather(coordinates) {
  return new Promise(function (resolve, reject) {
    new Request.JSON({
      url: '/echo/json/',
      data: {
        json: JSON.encode({ temperature: 'Too hot!' }),
        delay: 1
      },
      onSuccess: function (response) {
        resolve(response);
      }
    }).send();
  });
}

function showCurrentWeather(data) {
  var temp = document.getElementById('current-temperature');
  temp.textContent = data.temperature;
}

Return a promise that resolves when your original displayPosition was called. I added back that function back into getPreciseLocation because it was easier to get it working. You can also add back in your checks for geolocation here, and a reject as you see fit.

function getPreciseLocation() {
  return new Promise(function (resolve, reject) {
    navigator.geolocation.getCurrentPosition(function (position) {
      resolve([position.coords.latitude, position.coords.longitude]);
    });
  });
}

Here we just reduce the code footprint to call the relevant functions with the appropriate data.

function getWeatherWrapper() {
  getPreciseLocation()
    .then(getCurrentWeather)
    .then(showCurrentWeather);
}

var prompt = document.getElementById('precise-location-prompt');
prompt.addEventListener('click', getWeatherWrapper);

DEMO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM