变量在函数之外变得未定义

时间:2021-04-11 01:28:17

标签: javascript leaflet

所以我一直在使用 Leaflet.js 在我的家乡创建疫苗接种点的地图,并试图使用路由来找到离用户最近的站点,但是当我登录或尝试时,变量不知何故变得未定义在函数外调用它。我对 js 比较陌生,并且在 python 中使用 folium 时了解了传单。在 python 中,我认为你会声明你正在更改一个全局变量,或者更好地使用 return,但我不确定如何使用 js 和传单库来做到这一点。

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);

2 个答案:

答案 0 :(得分:1)

要了解此处的问题,请在 console.log( 'Calling L.Routing.control()', self_lat, self_long ) 调用之前添加一个 L.Routing.control() 调用(代码清单中的 ...)。

你会注意到两件事:

  1. 如您所知,self_latself_long 将出现在这里undefined。但为什么?
  2. 您还将看到这个新的 console.log() 在现有 console.log() 调用之前被调用,您将这些值记录到 onLocationFound 函数中。这就是问题的根源。

与其他 JavaScript 库和原生 JavaScript 本身中的许多类似函数一样,Leaflet 的 myMap.on( eventName, eventListener ) 函数是异步。这意味着 eventListener - 在本例中为 onLocationFound - 不会立即调用。稍后调用它, myMap.on() 调用本身返回之后。

JavaScript 中的所有异步回调/侦听器函数都以这种方式工作。设置全局变量很少有用,因为问题在于何时运行各种代码。

在不知道其余代码的情况下,我建议的一种可能解决方法是完全去掉 self_latself_long 变量,并移动 L.Routing.control() 调用 在您的 onLocationFound 函数中,如下所示:

var mymap = L.map('mapid').setView([34.7465, -92.2896], 6);
...
function onLocationFound(e) {
    console.log(e);
    L.marker(
        [e.latitude, e.longitude],
        {icon: home_marker}
    ).bindPopup("YOU ARE HERE!").addTo(mymap);

    L.Routing.control({
        waypoints: [
            L.latLng([e.latitude, e.longitude]),
            L.latLng([34.7465, -92.2896])
        ]
    }).addTo(mymap);
}

function onLocationError(e) {
    alert(e.message);
}
mymap.locate({setView: false, maxZoom: 16});
mymap.on('locationfound', onLocationFound);
mymap.on('locationerror', onLocationError);

这是一个非常简单的例子,可以帮助说明。我们进行了一个 setTimeout() 调用和三个 console.log() 调用:一个在回调之前,一个在之后,一个在回调内部。单击下面的运行按钮并注意日志消息的顺序:

console.log( 'Before setTimeout' );
setTimeout(
    function() {
        console.log( 'Inside setTimeout callback' );
    },
    1  // one millisecond delay
);
console.log( 'After setTimeout returns' );

当然 setTimeout() 这个名字更清楚地表明在调用回调函数之前会有延迟(即使只是一毫秒)。需要注意的是,所有 JavaScript 中的异步回调函数和事件侦听器都是这样工作的。

答案 1 :(得分:0)

如果 self_latself_long 不是全局变量,则通过只传递 onLocationFound 的原型而失去了上下文,该函数是在 {{1} 的上下文中调用的在这些变量不存在的情况下,要解决这个并将您的回调保持为一个单独的函数,您可以按如下方式调用它:

mymap