在 Meteor 的服务器上自动阻止 运行 方法
Prevent method from running automatically on server in Meteor
我试图在服务器文件夹中创建地理编码方法,但它抱怨页面加载时未定义地址。看起来该方法在输入具有值(或已被调用)之前在页面加载时触发并导致此行为。有没有办法让方法等待 运行 直到被调用而不是自动调用,或者解决这个问题的其他方法? Aldeed:geocoder 似乎只 运行 服务器端。
我的 coffeescript 方法,使用 aldeed:geocoder
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]
模板事件
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);
}
}
});
模板
<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>
styx 的点击事件再次更新
'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 );
});
}
},
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;
}
},
使用 aldeed:geocoder
Meteor 包有两个问题(还有一个问题):
-
Geocoding an address is simple. Get a new instance of GeoCoder and then call the geocode method on it, passing in the address string.
这意味着,与 npm 包不同,geocode()
函数期望第一个参数是一个字符串 — 您要进行地理编码的地址 (source code)
来自同一文档:
Note that unlike in the node package, the geocode method is synchronous. This makes it simple to use in a server method. If you prefer to pass a callback as the last argument, you can.
这意味着,您的服务器方法可以(并且应该)利用:
geocodeAddress: (address) ->
geocoder = new GeoCoder
httpAdapter: 'https'
apiKey: 'AIzaSyDYjLGrETRt4hPZtXcmzQwRbzlFT1zWwr8'
result = geocoder.geocode(address).pop()
[ result.latitude, result.longitude ]
正如 Michel Floyd 在评论中指出的那样,客户端上的 Meteor.call
是 异步的 ,因此您应该这样做:
Meteor.call('geocodeAddress', customLocationValue, (err, result) => {
if (err) {
// handle error
return;
}
const [ lat, lng ] = result;
// handle success
});
添加:来自geocode(address)
的响应(从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' } ]
我试图在服务器文件夹中创建地理编码方法,但它抱怨页面加载时未定义地址。看起来该方法在输入具有值(或已被调用)之前在页面加载时触发并导致此行为。有没有办法让方法等待 运行 直到被调用而不是自动调用,或者解决这个问题的其他方法? Aldeed:geocoder 似乎只 运行 服务器端。
我的 coffeescript 方法,使用 aldeed:geocoder
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]
模板事件
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);
}
}
});
模板
<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>
styx 的点击事件再次更新
'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 );
});
}
},
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;
}
},
使用 aldeed:geocoder
Meteor 包有两个问题(还有一个问题):
-
Geocoding an address is simple. Get a new instance of GeoCoder and then call the geocode method on it, passing in the address string.
这意味着,与 npm 包不同,
geocode()
函数期望第一个参数是一个字符串 — 您要进行地理编码的地址 (source code) 来自同一文档:
Note that unlike in the node package, the geocode method is synchronous. This makes it simple to use in a server method. If you prefer to pass a callback as the last argument, you can.
这意味着,您的服务器方法可以(并且应该)利用:
geocodeAddress: (address) -> geocoder = new GeoCoder httpAdapter: 'https' apiKey: 'AIzaSyDYjLGrETRt4hPZtXcmzQwRbzlFT1zWwr8' result = geocoder.geocode(address).pop() [ result.latitude, result.longitude ]
正如 Michel Floyd 在评论中指出的那样,客户端上的
Meteor.call
是 异步的 ,因此您应该这样做:Meteor.call('geocodeAddress', customLocationValue, (err, result) => { if (err) { // handle error return; } const [ lat, lng ] = result; // handle success });
添加:来自geocode(address)
的响应(从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' } ]