Leaflet JS:在承诺中定义更新功能;教程的变化

Leaflet JS: defining update function within promise; variation on tutorial

本教程的变体:https://leafletjs.com/examples/choropleth/。我正在尝试添加自定义信息控件。

let info = L.control();
function highlightFeature(e) {
    ...
    info.update(layer.feature.properties);
}

function resetHighlight(e) {
    ...
    info.update();
}

function updateFunction(tab, props) {
    this._div.innerHTML = '<h4>US Active Covid-19 Cases </h4>' +  (props ?
        '<b>' + props.name + '</b><br />' + getActive(tab, props.name) + ' cases'
        : 'Hover over a state');
}

info.onAdd = function(map) {
    this._div = L.DomUtil.create("div", "info");
    this.update();
    return this._div;
}

let statedata = fetch(url + stateurl).then(data => data.json());
statedata.then((data) => {
    info.update = (props) => updateFunction(data, props);
    let style = (feature) => styleMap(data, feature); 
    info.addTo(mymap);

    geojson = L.geoJson(statesData, {style : style, onEachFeature: onEachFeature}).addTo(mymap);    
});

在这里,我的info.update与教程略有不同。 info.updatestyle 取决于我只能在底部的异步部分中访问的 json 数据。但是,此代码给我以下错误:Uncaught (in promise) TypeError: Cannot set property 'innerHTML' of undefined,指的是 updateFunction 的 this._div 行。

我发现如果我执行以下任一操作

  1. 移动 let info = L.control() 和我所有依赖于 info 的函数或
  2. 在 promise 之外定义 info.update

那么代码将正常运行。然而,选项 1 看起来很可怕并且在道德上是不正确的,选项 2 使我不得不放弃访问状态数据的希望 json。另外,在选项 2 中,我不明白在承诺内部或外部声明 info.update 有什么区别。特别是,为什么在 promise 内声明 info.update 会导致 info._div 的未定义行为,而在 promise 外声明 info.update 则不会?

如能提供任何关于此处错误的线索,我们将不胜感激!

在您使用的教程中,这是他们为 info.update:

info.update = function (props) {
    this._div.innerHTML = '<h4>US Population Density</h4>' +  (props ?
        '<b>' + props.name + '</b><br />' + props.density + ' people / mi<sup>2</sup>'
        : 'Hover over a state');
};

在此函数中,this 将引用 info 对象。在您的代码中,您重构为:

function updateFunction(tab, props) {
    this._div.innerHTML = '<h4>US Active Covid-19 Cases </h4>' +  (props ?
        '<b>' + props.name + '</b><br />' + getActive(tab, props.name) + ' cases'
        : 'Hover over a state');
}
// ...
info.update = (props) => updateFunction(data, props);

通过使用调用常规函数的箭头函数,您有效地切断了 infothis 之间的联系。在您的情况下,this 可能默认为 window,这可以解释为什么 _div 未定义。

要解决此问题,您需要明确地 bind thisinfo。你可以这样做:

info.update = (props) => updateFunction.bind(info)(data, props);

或者更简洁,您可以简单地绑定 this 和第一个参数,并完全跳过中间的箭头函数:

info.update = updateFunction.bind(info, data);