2017-10-02 4 views
0

En essayant de créer une méthode de géocodage dans le dossier du serveur mais en me plaignant que cette adresse n'est pas définie au chargement de la page. Il semble que la méthode se déclenche au chargement de la page avant que l'entrée ait une valeur (ou ait été appelée) et provoque ce comportement. Existe-t-il un moyen d'attendre que la méthode soit exécutée jusqu'à ce qu'elle soit appelée au lieu de l'être automatiquement ou d'une autre manière? Aldeed: geocoder semble seulement tourner côté serveur.Empêcher la méthode de s'exécuter automatiquement sur le serveur dans Meteor

Ma méthode coffeescript, en utilisant aldeed: géocodage

geocodeAddress: (address) -> 
lat = '' 
lng = '' 
    addressVar = '' 
    geocoder = new GeoCoder(
     geocoderProvider: 'google' 
     httpAdapter: 'https' 
     apiKey: 'AIzaSyDYjLGrETRt4hPZtXcmzQwRbzlFT1zWwr8') 
    geocoder.geocode { 'address': address }, (results, status) -> 
     if status == google.maps.GeocoderStatus.OK 
      lat = results[0].geometry.location.lat() 
      lng = results[0].geometry.location.lng() 
      return [lat,lng] 

L'événement Modèle

Template.dashboard.events({ 
    'click #customlocationsubmit'(evt) { 
    if (document.getElementById("customlocation")) { 
     customLocationValue = document.getElementById("customlocation").value; 
    } 
    if (typeof customLocationValue === 'undefined' || customLocationValue == "") { 
     return false; 
    } else { 
    customUserLocation = Meteor.call('geocodeAddress',customLocationValue); 
    } 
    } 
}); 

Le modèle

<template name="dashboard"> 
    <div class="template-dashboard"> 
     <div class="container"> 
      <div class="row"> 
       <div class="col-md-3"> 
        {{> addPost}} 
        {{> favoritesSidebar}} 
       </div> 
       <div class="col-md-9"> 
       <button id="customlocationsubmit" type="submit" class="btn btn-primary">Update</button> 

        {{> posts}} 
       </div> 
      </div> 
     </div> 
    </div> 
</template> 

événement Click pour Styx mis à jour à nouveau

'click #customlocationsubmit'(evt) { 
    if (document.getElementById("customlocation")) { 
     customLocationValue = document.getElementById("customlocation").value; 
    } 
    if (typeof customLocationValue === 'undefined' || customLocationValue == "") { 
     return false; 
    } else { 
    Meteor.call('geocodeAddress', customLocationValue, (err, result) => { 
    if (err) { 
     // handle error 
     return; 
    } 
    const [ lat, lng ] = result; 
    geoResult = result; 
    const sortOrder = (Session.get('posts.sortBy') || {}).date || 1; 
    return Session.set('posts.sortBy', {date: -sortOrder}); 
    return distanceFilter(this, geoResult); 
    }); 
    } 

    }, 

fonction d'aide pour Styx

distanceFilter(location,customUserLocation) { 
    function getDistanceFromLatLonInMi(lat1,lon1,lat2,lon2) { 
     var R = 6371; // Radius of the earth in km 
     var dLat = deg2rad(lat2-lat1); // deg2rad below 
     var dLon = deg2rad(lon2-lon1); 
     var a = 
     Math.sin(dLat/2) * Math.sin(dLat/2) + 
     Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
     Math.sin(dLon/2) * Math.sin(dLon/2) 
     ; 
     var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
     var d = R * c; // Distance in km 
     var e = d * 0.621371; 
     return e; 
    }; 

    function deg2rad(deg) { 
     return deg * (Math.PI/180); 
    }; 

    getUser = Meteor.users.findOne({ 
     _id: Meteor.userId() 
    }); 
    if (getUser){ 
    userUserName = getUser.username; 
    userLocation = getUser.profile.location.split(','); 
    }; 
    eventLocation = location.split(','); 
    if (typeof customLocationValue === 'undefined' || customLocationValue == "") { 
     customUserLocationVar = userLocation; 
    } 
     else { 
     customUserLocationVar = customUserLocation; 
     console.log(customUserLocation); 
     } 
    distance = getDistanceFromLatLonInMi(customUserLocationVar[0],customUserLocationVar[1],eventLocation[0],eventLocation[1]); 
    eventDistance = Math.round(distance); 
    filterValue = jQuery('#eventdistance').val(); 
    if (filterValue) { 
     if (eventDistance <= filterValue) { 
     return true; 
     } 
    } else if (eventDistance <= 20) { 
      return true; 
    } else { 
      return false; 
    } 

    }, 
+0

Où est la définition de la méthode (côté serveur) et le code qui appelle cette méthode du client? –

+0

La méthode est dans le dossier du serveur. La méthode est appelée à partir d'une fonction d'aide à l'intérieur d'un modèle dans une vue – Silicabello

+0

Veuillez montrer le code de la méthode et votre code client - le code ci-dessus est presque complètement hors de propos pour votre problème. Aussi - n'appelez pas les méthodes des helpers, appelez les depuis * events * à la place. Les assistants courent plus souvent que prévu. –

Répondre

1

Il y a deux problèmes avec votre utilisation de aldeed:geocoder package Meteor (et un autre numéro):

  1. De l'package documentation:

    géocodage une adresse est simple. Obtenez une nouvelle instance de GeoCoder, puis appelez la méthode geocode, en transmettant la chaîne d'adresse.

    Cela signifie que, à la différence dans le paquet de NPM, la fonction geocode() attend à ce premier argument est une chaîne - l'adresse que vous souhaitez géocodage (source code)

  2. De la même documentation:

    Notez que contrairement au package de noeud, la méthode de géocodage est synchrone. Cela le rend simple à utiliser dans une méthode de serveur. Si vous préférez passer un rappel comme dernier argument, vous pouvez le faire.

    Cela signifie que votre méthode de serveur pourrait (et devrait) utiliser que:

    geocodeAddress: (address) -> 
        geocoder = new GeoCoder 
        httpAdapter: 'https' 
        apiKey: 'AIzaSyDYjLGrETRt4hPZtXcmzQwRbzlFT1zWwr8' 
    
        result = geocoder.geocode(address).pop() 
    
        [ result.latitude, result.longitude ] 
    
  3. Comme il a déjà été souligné dans les commentaires de Michel Floyd, Meteor.call sur le client est asynchrone, donc vous devriez le faire comme ceci:

    Meteor.call('geocodeAddress', customLocationValue, (err, result) => { 
        if (err) { 
        // handle error 
        return; 
        } 
        const [ lat, lng ] = result; 
        // handle success 
    }); 
    

Ajout: Réponse de geocode(address) (exécutée à partir meteor shell):

> g.geocode('02068, Ukraine, Kiev') 
[ { formattedAddress: 'Kiev, Ukraine, 02000', 
    latitude: 50.4501, 
    longitude: 30.5234, 
    extra: 
    { googlePlaceId: 'ChIJBUVa4U7P1EARxX1LbAvqE6A', 
     confidence: 0.5, 
     premise: null, 
     subpremise: null, 
     neighborhood: null, 
     establishment: null }, 
    administrativeLevels: { level2long: 'Kyiv City', level2short: 'Kyiv City' }, 
    zipcode: '02000', 
    city: 'Kiev', 
    country: 'Ukraine', 
    countryCode: 'UA' } ] 
+0

Ceci est clairement la bonne réponse, mais je ne suis pas défini quand j'appelle le const [lat, lng] en dehors de la méthode dans l'événement. J'ai essayé de définir la méthode entière à une variable, et de définir une variable dans le résultat de l'appel, mais toujours indéfini. – Silicabello

+0

@Silicabello Avec 'coffeescript' vous devriez accorder une attention supplémentaire aux retraits et aux retours. Comme vous pouvez le voir, mon exemple de méthode meteor n'a pas d'instruction 'return', parce que dans le' coffeescript' la dernière instruction est toujours retournée. Si vous avez ajouté quelque chose _after_ cela - il ne sera pas retourné. – Styx

+0

@Silicabello Essayez d'ajouter 'console.debug (result)' à votre rappel de 'Meteor.call' pour voir ce qui est retourné. – Styx