Javascript 变量在函数外部变得未定义
因此,我一直在使用moulate.js创建我家乡州疫苗接种站点的地图,并试图使用路由查找离用户最近的站点,但当我登录或尝试在函数外部调用该变量时,该变量不知何故变得未定义。我对js比较陌生,在python中使用folium时了解了传单。在python中,我认为您应该声明您正在更改一个全局变量,或者更好地使用return,但我不确定如何使用js和传单库实现这一点Javascript 变量在函数外部变得未定义,javascript,leaflet,Javascript,Leaflet,因此,我一直在使用moulate.js创建我家乡州疫苗接种站点的地图,并试图使用路由查找离用户最近的站点,但当我登录或尝试在函数外部调用该变量时,该变量不知何故变得未定义。我对js比较陌生,在python中使用folium时了解了传单。在python中,我认为您应该声明您正在更改一个全局变量,或者更好地使用return,但我不确定如何使用js和传单库实现这一点 var self_lat; var self_long; ... var mymap = L.map('mapid').setView(
var self_lat;
var self_long;
...
var mymap = L.map('mapid').setView([34.7465, -92.2896], 6);
...
function onLocationFound(e) {
console.log(e);
self_lat = e.latitude;
self_long = e.longitude;
L.marker([e.latitude, e.longitude], {icon: home_marker}).bindPopup("YOU ARE HERE!").addTo(mymap);
console.log(typeof(e.latitude))
console.log(typeof(e.longitude))
}
function onLocationError(e) {
alert(e.message);
}
mymap.locate({setView: false, maxZoom: 16});
mymap.on('locationfound', onLocationFound);
mymap.on('locationerror', onLocationError);
...
L.Routing.control({
waypoints: [
L.latLng([self_lat, self_long]),
L.latLng([34.7465, -92.2896])
]
}).addTo(mymap);
如果
self\u lat
和self\u long
不是全局变量,则通过仅传递onLocationFound
的原型,正在mymap
的上下文中调用该函数,而这些变量不存在,要解决此问题并将回调作为一个单独的函数,可以按如下方式调用它:
mymap.on('locationfound', (e) => onLocationFound(e));
要理解这里的问题,请在调用
L.Routing.control()
之前添加一个console.log('Calling L.Routing.control()',self\u lat,self\u long)
调用(代码列表中有…
)
你会注意到两件事:
self\u lat
和self\u long
将在此处未定义。但是为什么呢
console.log()
调用之前调用了这个新的console.log()
,您可以在onLocationFound
函数中记录这些值。这就是问题的根源myMap.on(eventName,eventListener)
函数是异步的。这意味着不会立即调用eventListener
——在本例中,onLocationFound
。在myMap.on()
调用本身返回后的某个时间调用它
JavaScript中的所有异步回调/侦听器函数都是这样工作的。设置全局代码很少有用,因为问题是当各种代码位运行时
在不了解其余代码的情况下,我可能建议的一种可能的修复方法是完全去掉self\u lat
和self\u long
变量,并将L.Routing.control()
调用移动到onLocationFound
函数中,如下所示:
var mymap=L.map('mapid').setView([34.7465,-92.2896],6);
...
函数onLocationFound(e){
控制台日志(e);
L.标记(
[e.纬度,e.经度],
{图标:主标记}
).bindpoppop(“您在这里!”).addTo(mymap);
路由控制({
航路点:[
L.纬度([e.纬度,e.经度],
L.latLng([34.7465,-92.2896])
]
}).addTo(mymap);
}
函数onLocationError(e){
警报(e.message);
}
locate({setView:false,maxZoom:16});
mymap.on('locationfound',onLocationFound);
mymap.on('locationerror',onLocationError);
下面是一个非常简单的例子,有助于说明。我们进行一个setTimeout()
调用和三个console.log()
调用:一个在回调之前,一个在回调之后,一个在回调内部。单击下面的运行按钮并记下日志消息的顺序:
console.log('Before setTimeout');
设置超时(
函数(){
log('Inside setTimeout callback');
},
1//1毫秒延迟
);
log('After setTimeout returns')代码>map.on('locationFound',onLocationFound){…
在这里的语法不正确。要么提供回调处理程序,要么提供回调函数,但你不能同时做这两件事。你能解释一下吗?你已经编辑了代码,所以你只提供了一个处理程序-这是一种方法(应该可以正常工作)。另一种方法是使用内联函数执行类似的操作(使用“箭头函数”):mymap.on('locationfound',()=>{/*dostuff here*/});
在当前状态下不起作用。当我当前运行它时,它说self_lat和self_long仍然未定义。我尝试过它,但它似乎不起作用。当我当前运行它时,它说self_lat和self_long仍然未定义。嗯,奇怪,这意味着您的变量实际上是在不同的上下文中声明的,而不是您所处的上下文对映射进行判断,您是否使用任何框架来执行此操作,或者它只是一个普通的javascript文件?思考……您的问题可能与回调无关,但在L.路由部分,这可能是一个无辜的问题,在声明它们时,只需尝试为self_lat和self_long分配一个默认值,例如:var self_lat=0;var self_long=0;是的,发生的是值不会改变。啊,好的,谢谢。有什么方法可以使它同步或以其他方式保存它吗?我想使用路由控制来找到从您的位置到所有接种位置的距离和时间,并绘制最佳位置。JavaScript确实有办法发出远程请求就像这个同步的,但我不知道这个传单API是否支持它。无论如何,你不应该使用它,因为它会在等待服务器响应时锁定整个浏览器:如果服务器没有响应,用户甚至无法关闭页面。有一种方法可以让JavaScript代码感觉更像用Python编写的同步代码:async
/wait
。如果传单映射的on
方法返回一个Promise
,这将非常容易实现。我仍然建议您熟悉老式技术,在事件侦听器函数中(或在调用的函数中,无论哪种方式,都是一样的)执行所有操作,因为它将有助于理解异步代码是如何工作的。