Leaflet JS中使用$.when().then()仍提前触发AJAX加载报addTo未定义错误
问题核心原因
你这个报错和siblingMarkers不显示的问题,本质是异步请求的时序和依赖逻辑写错了,主要有3个问题:
$.when()要求传入的参数必须是jQuery Deferred对象才能正确等待请求完成,但是你的getPopularCities()方法没有返回内部AJAX的Deferred对象,导致$.when()根本没等getPopularCities内部的三层嵌套AJAX跑完,就执行了后面的then回调。这时候siblingMarkers还没初始化赋值,调用addTo自然就报undefined的错。- 你把
getPopularCities()和getGeoNameId()放在$.when里并行执行,但getPopularCities内部请求getCountrySiblings.php的时候需要用到geoNameId作为参数,并行执行的情况下很可能请求sibling接口的时候geoNameId还没返回,导致接口请求失败,拿不到sibling数据。 - 你在
getPopularCities最内层的机场接口成功回调里已经调用过airportMarkers.addTo、cityMarkers.addTo、siblingMarkers.addTo了,又在$.when的then回调里重复调用了一次,完全多余,而且时序不对的情况下重复调用还会报错。
解决步骤
调整请求顺序,保证依赖参数先获取
把getGeoNameId()从$.when的并行列表里拿出来,放到getPopularCities()之前执行,等geoNameId拿到之后再调用getPopularCities(),保证sibling接口的参数是有效的。给异步方法返回Deferred对象
修改getPopularCities()方法,在最开头返回内部最外层的AJAX对象,这样$.when就能正确等待它内部所有嵌套AJAX都执行完:
function getPopularCities() { let cityPopulation = []; cityMarkers = new L.MarkerClusterGroup(); if (mainLayer) { currentMap.removeControl(mainLayer); } // 这里加return,把AJAX的Deferred对象返回出去 return $.ajax({ // 原有代码不变... }) }
其他你放到$.when里的异步方法比如getCityWeatherList之类的,也都要返回对应的AJAX Deferred对象,否则$.when的等待逻辑都不生效。
- 删掉重复的addTo调用
把$.when的then回调里这三行删掉,因为你已经在getPopularCities内部加过了:
airportMarkers.addTo(currentMap); cityMarkers.addTo(currentMap); siblingMarkers.addTo(currentMap);
- 加兜底逻辑避免报错
可以在getPopularCities最开头先给siblingMarkers初始化空的图层组,就算sibling接口请求失败也不会出现undefined的报错:
function getPopularCities() { let cityPopulation = []; cityMarkers = new L.MarkerClusterGroup(); siblingMarkers = new L.MarkerClusterGroup(); // 提前初始化 // 原有代码不变... }
改完之后siblingMarkers就能正常加载显示,也不会再报addTo的undefined错误了。
内容的提问来源于stack exchange,提问作者user16431107
相关产品推荐
相关产品推荐

