Home > Software engineering >  Function parameter is not defined in callback
Function parameter is not defined in callback

Time:02-25

I am trying to get the location of the user and using that I am trying to get the city. I don't why but when I call the query function, the city parameter is having some value but it is not reflected in the callback function's if condition. However, if I replace the city variable in the If condition with the common String callback function works fine. the data variable is the array of objects

var data = [{ District: "surat", Specialties: "eye" }, ...., {}];
getLocation();
function getLocation() {
  var lat = "";
  var lon = "";
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showPosition, showError);
  } else {
    console.log("denied");
  }
}

function showPosition(position) {
  console.log("2");
  lat = position.coords.latitude;
  lon = position.coords.longitude;
  console.log(lat);
  console.log(lon);
  displayLocation(lat, lon);
}

function showError(error) {
  switch (error.code) {
    case error.PERMISSION_DENIED:
      console.log("User denied the request for Geolocation.");
      break;
    case error.POSITION_UNAVAILABLE:
      console.log("Location information is unavailable.");
      break;
    case error.TIMEOUT:
      console.log("The request to get user location timed out.");
      break;
    case error.UNKNOWN_ERROR:
      console.log("An unknown error occurred.");
      break;
  }
}

async function displayLocation(latitude, longitude) {
  let city = "";
  var geocoder;
  geocoder = new google.maps.Geocoder();
  var latlng = new google.maps.LatLng(latitude, longitude);

  await geocoder.geocode(
    {
      latLng: latlng,
    },
    function (results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        console.log(results);
        if (results[0]) {
          var add = results[0].formatted_address;
          var value = add.split(",");

          count = value.length;
          country = value[count - 1];
          state = value[count - 2];
          city = value[count - 3];

          console.log(city);
        } else {
          console.log("not found");
        }
      } else {
        console.log(status);
      }
    }
  );
  await query(city);
}

function query(city) {
  console.log(city); // it is printing Correctly

  var hospitals = data.filter((val) => {
    if (
      val["District"] === city &&
      val["Specialties"].toLowerCase().indexOf("eye") != -1
    ) {
      return true; //instead of city(parameter) if I put a String(For Example"Boston") it works completely fine.
    }
  });
  console.log(hospitals); //hospital array is empty instead of having some value
}

CodePudding user response:

You have to return false in the filter, if it is not passing your condition - thus, it is better to just write:

return val['District'] === city && val['Specialties'].toLowerCase().indexOf("eye") != -1

In this case the return value is going to be Boolean (true if passes, false if not).

Also, the data variable is not defined in the function. It's better to pass it in as an argument.

And also: the objects in the data array have a key called Specialities, but you are filtering for Specialties

const data = [{
    District: "city1",
    Specialties: "yeseye1",
  },
  {
    District: "city1",
    Specialties: "noye1",
  },
  {
    District: "city1",
    Specialties: "yeseye2",
  },
]

console.log('====== old query ======')

function query(city) {
  console.log(city); // it is printing Correctly

  var hospitals = data.filter((val) => {
    if (val['District'] === city && val['Specialties'].toLowerCase().indexOf("eye") != -1) {
      return true; //instead of city(parameter) if I put a String(For Example"Boston") it works completely fine.
    }
  });
}

const a = query("city1")
console.log(a)

console.log('====== newQuery ======')
const newQuery = (city, data) => data.filter((val) => val['District'] === city && val['Specialties'].toLowerCase().indexOf("eye") != -1)

const b = newQuery("city1", data)
console.log(b)

EDIT: AVOIDING TYPOS

There's a way to avoid typos like the one in your code: use constants:

const DIST = "District"
const SPEC = "Specialities"
const EYE = "eye"

const data = [{
    [DIST]: "city1",
    [SPEC]: "yeseye1",
  },
  {
    [DIST]: "city1",
    [SPEC]: "noye1",
  },
  {
    [DIST]: "city1",
    [SPEC]: "yeseye2",
  },
]

const newQuery = (city, data) => data.filter((val) => val[DIST] === city && val[SPEC].toLowerCase().indexOf(EYE) != -1)

const b = newQuery("city1", data)
console.log(b)

This way you can choose easier words instead of complicated strings.

EDIT 2

Also, you could update this solution if you'd set up the function(s) a bit differently:

const DIST = "District"
const SPEC = "Specialities"
const EYE = "eye"

const data = [{
    [DIST]: "city1",
    [SPEC]: "yeseye1",
  },
  {
    [DIST]: "city1",
    [SPEC]: "noye1",
  },
  {
    [DIST]: "city1",
    [SPEC]: "yeseye2",
  },
]

const curriedQuery = (data) => (filterTerm) => (city) => data.filter((val) => val[DIST] === city && val[SPEC].toLowerCase().indexOf(filterTerm) != -1)

const queryWithCityList = curriedQuery(data) // this sets the list of cities
const queryCityListForEye = queryWithCityList(EYE) // this sets the type of hospitals

const c = queryCityListForEye("city1") // this queries the hospitals in one city -> and gives you the result
console.log(c)

This solution seems a bit better if you filter the data source for a certain type of hospital many times over. As you create functions by passing in arguments one by one they are cached (by V8), so working with them becomes faster. (At least theoretically.)

  • Related