首页 > 解决方案 > Leaflet.js TypeError: t is undefined with multiple maps

问题描述

我正在尝试使用 leaflet.js 和 mapquests API 在一个页面上显示三张地图。我创建了一个 jQueryfor-loop来读取唯一的邮政编码,然后将其(通过 mapquest)转换为纬度和经度,最后创建三个地图,并将匹配的纬度和经度添加到每个地图。这将产生三个不同的地图,显示在一页上。

我用下面的代码在某种程度上实现了这一点。每张“卡”都有自己的卡号(从1到3)、邮政编码,以及对应的地图和地图ID。

编辑我也得到这个 jQuery 错误:

jQuery.Deferred exception: t is undefined addTo@https://unpkg.com/leaflet@1.6.0/dist/leaflet.js:5:64070
MYWEBSITEURL/map.js:38:6
e@https://code.jquery.com/jquery-3.5.1.min.js:2:30005
l/</t<@https://code.jquery.com/jquery-3.5.1.min.js:2:30307
 undefined

我现在遇到的问题是,当我的 jQuery 运行时,我得到了这个控制台错误:TypeError: t is undefined. 我已将其范围缩小到与L.tileLayer()and/orL.circle()函数有关的内容。我在页面中添加了最新的 jQuery 和 leaflet.js。

编辑在@ivansanchez 回答后更改了问题,但问题仍然相同。

编辑更改leaflet.jsleaflet-sr.js,我现在得到错误:TypeError: map is undefined

地图.js:

$(document).ready(function(){

var postalCodes = [];
var latLng      = [];
var lat         = [];
var lng         = [];
var maps        = [];

for(var n = 0; n < 3; n++) {

    console.log('Maps for-loop count: '+n);

    postalCodes.push($('.card'+[n]+' .card__info--postal > span').html());

    $.ajax({ // Get lat & long from postal code
        async: false,
        url: 'https://www.mapquestapi.com/geocoding/v1/address?key=MYAPIKEY&postalCode='+postalCodes[n]+'&country=finland',
        success: function(obj) {
            latLng[n] = obj.results[0].locations[0].latLng;
            lat[n]    = latLng[n].lat;
            lng[n]    = latLng[n].lng;
        },
        error: function(xhr) {
            console.log('Map error', xhr);
        }
    });

    console.log(latLng[n], lat[n], lng[n]);

    var map = L.map('mapid'+[n]).setView([lat[n], lng[n]], 13);

    L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
        maxZoom: 18,
        id: 'mapbox/streets-v11',
        tileSize: 512,
        zoomOffset: -1,
        accessToken: 'MYAPIKEY'
    }).addTo(maps[n]);

    L.circle([lat[n], lng[n]], { // Map out area of the postal code
        color: 'rgb(218, 65, 103)',
        fillColor: 'rgb(218, 65, 103)',
        fillOpacity: 0.5,
        radius: 500
    }).addTo(maps[n]);

    maps.push(map);
}
});

标签: jqueryleaflet

解决方案


你正在做的...

 var maps = [ L.map('mapid'+[n]).setView([lat[n], lng[n]], 13) ]; // Creates three maps, that corresponds with three mapids in my HTML

......这并不像你认为的那样。您正在创建一个包含一个元素的数组,并将其分配给maps,并且您这样做了三遍。因此,在循环的第二遍,当代码引用 时maps[1],它有一个undefined值。

相反,您可能想做类似...

var maps = [];
for(var n = 0; n < 3; n++) {
   /* stuff */
   maps.push( L.map( /*stuff*/ ) );
   L.tileLayer( /* stuff */ ).addTo(maps[n]);
}

...甚至...

var maps = [];
for(var n = 0; n < 3; n++) {
   /* stuff */
   var map = L.map( /*stuff*/ );
   L.tileLayer( /* stuff */ ).addTo(map);
   maps.push(map);
}

另一方面,关于 和 的值,你有一个很好的竞争条件。由于这些值仅在网络操作完成时设置(因为 AJAX 是异步等),所以它们(很可能)在使用时才设置。您可能希望延迟向每个地图添加数据,直到您实际获得所述数据,例如latLng[n]lat[n]lng[n]undefined

var maps = [];
for(var n = 0; n < 3; n++) {
   var map = L.map( /*stuff*/ );
   fetch(url)
     .then(function(response){return response.json})
     .then(function(json)){
       L.circle(json.results[0].locations[0]).addTo(map);
     });
   L.tileLayer( /* stuff */ ).addTo(map);
   maps.push(map);
}

注意这里的事件顺序是:发起网络请求,实例化地图,实例化tilelayer,网络请求完成,实例化圆。

(为什么是的,我更喜欢 fetch API而不是 jQuery)。

请记住,在 Leaflet 中,更改leaflet.jsleaflet-src.js以获得更好的堆栈跟踪通常很好,并且使用浏览器的开发人员工具在异常之前设置断点将允许您查看当时的值undefined


推荐阅读