Случайные двойные циклы в JavaScript

Я создал приложение, в котором вы можете выбрать таблицу в базе данных, а затем отобразить данные на карте Leaflet. Данные имеют соответствующую легенду.

Я хочу, чтобы мое приложение принимало различные наборы данных и отображало их на карте с минимальными программными изменениями. Это новое требование, и я изменил свой предыдущий код, но он не оптимален.

Код, который у меня сейчас есть, перебирает набор данных, чтобы назначить цвет определенному значению, но он также перебирает набор данных, чтобы извлечь уникальные значения, чтобы я мог использовать их в легенде.

Это приводит к тому, что мое приложение имеет цикл в цикле, создавая ненужные вычисления. Это не проблема с небольшим набором данных, 19 записей x19 выполнимо, но 8062x8062...

Проблема заключается в цикле for в функции getColor(). Я пытался переместить цикл for в новую функцию (getColor v2), но всегда терял arrayMetKetens. Я думаю, что getColor() запускается до того, как getArray() сможет вернуть свое значение, но поскольку многие функции начинают работать, как только я выбираю таблицу, я не могу заставить getArray() вернуть ее быстрее. Или есть?

Код для добавления цвета маркерам/многоугольникам:

window["mapDataLayer"] = L.geoJson(geojson_dataTable, {
    pointToLayer: function (feature, latlng) {
        var markerStyle = { 
            fillColor: getColor(feature.properties.Fastfoodketen),
            color: "#696969",
            fillOpacity: 0.6,
            opacity: 0.9,
            weight: 1,
            radius: 8
        };
        return L.circleMarker(latlng, markerStyle);
    },

     style: function (feature){
         if(feature.geometry.type === 'MultiPolygon'){
             var polygonStyle = {
            fillColor: getColor(feature.properties.Naam),
            color: "grey",
            weight: 5,
            opacity: 1
            };
         }
         else{
             return null;
         }
         return polygonStyle;
     }
}).addTo(map);

функция getColor:

function getColor(keten) {
    checkTable();
    var ketens = [];

    for(i=0;i<(geojson_dataTable.features).length;i++){
        ketens = ketens.concat(Object.byString(geojson_dataTable, 'features['+i+'].properties.'+featureVoorSorteer))
    }
    console.log(ketens);
    arrayMetKetens = (jQuery.unique( ketens ));
    var i = arrayMetKetens.indexOf(keten);

    if (i !== -1) {
        return arrayKleur[ i ];
        } 
    else {
        return '#999999';
    } 
}

getColor v2:

function getArray(){
    var ketens = [];
    for(i=0;i<(geojson_dataTable.features).length;i++){
        ketens = ketens.concat(Object.byString(geojson_dataTable, 'features['+i+'].properties.'+featureVoorSorteer))
        console.log(ketens);
    }
    arrayMetKetens = (jQuery.unique( ketens ));
    return arrayMetKetens.
}

function getColor(keten) {
    checkTable();
    getArray();
    yMetKetens.indexOf(keten);
    if (i !== -1) {
        return arrayKleur[ i ];
        } 
    else {
        return '#999999';
    } 
    console.log("hij doet het")
}

person Jordi Z    schedule 28.06.2016    source источник
comment
Я думаю, вы должны задать новый вопрос, если у вас есть новая проблема. Тем не менее: если ваша проблема такая, как вы ожидаете, ее должно быть легко подтвердить, добавив несколько console.log() в разных местах вашего кода, чтобы проверить, соответствует ли порядок выполнения ожидаемому.   -  person Jieter    schedule 29.06.2016
comment
Ваше право, будет откат и сделать новый вопрос.   -  person Jordi Z    schedule 29.06.2016


Ответы (1)


Прежде всего, если вы не возражаете, что я комментирую стиль программирования JS, этот код... ну... далек от совершенства :-) В частности, косвенное использование глобальной переменной затрудняет чтение. Я попытаюсь попробовать и предложить что-то, что не подразумевает «переписать все целиком».

Я буду следить за использованием глобальных переменных в функциях, хотя это обычно считается антишаблоном.

Во-первых, если код, который вы отправили как «getColor v2», является ФАКТИЧЕСКИМ кодом, то в нем есть очевидная ошибка:

function getColor(keten) {
    checkTable();
    getArray();
    //yMetKetens.indexOf(keten);<-- looks like partialy copied code :-)
    // SHOULD BE THIS:
    var i = arrayMetKetens.indexOf(keten);
    if (i !== -1) {
        return arrayKleur[ i ];
        } 
    else {
        return '#999999';
    } 
    console.log("hij doet het")
}

С этим фиксированным у нас все еще есть вызов getArray() каждый раз, когда мы вызываем getColor(). Но сначала давайте посмотрим на немного улучшенную версию getArray():

function getArray(){
    var ketens = [];
    //for(i=0;i<(geojson_dataTable.features).length;i++){
    //    ketens = ketens.concat(Object.byString(geojson_dataTable, 'features['+i+'].properties.'+featureVoorSorteer))
    //    console.log(ketens);
    //}
    //THE CODE ABOVE CAN BE SIMPLY EXPRESSED AS
    for(i=0;i < geojson_dataTable.features.length;i++){
       ketens = keten.concat(geojson_dataTable.features[i].properties[featureVoorSorteer])
    }
    //lets use global variable arrayMetKetens explicitly 
    window.arrayMetKetens = jQuery.unique( ketens );
    //return arrayMetKetens <-- we never use the return value of the function anyway...

}

теперь мы можем немного изменить нашу функцию getColor():

function getColor(keten) {
    checkTable();
    //getArray(); <--REMOVE CALL TO getArray()
    var i = window.arrayMetKetens.indexOf(keten);//<-- explicit use of global variable we initialise in getArray()
    if (i !== -1) {
        return arrayKleur[ i ];
        } 
    else {
        return '#999999';
    } 
    console.log("hij doet het")
}

И последнее, что нам нужно сделать, это вызвать getArray(), как только у нас появится geojson_dataTable объект. В отправленном вами коде нет этой части, поэтому давайте поместим ее здесь:

getArray();//<-- calling getArray() here will initialise (once) the array arrayMetKetens 
           //    which then can be used in the function getColors()
window["mapDataLayer"] = L.geoJson(geojson_dataTable, {
    pointToLayer: function (feature, latlng) {
        var markerStyle = { 
            fillColor: getColor(feature.properties.Fastfoodketen),
            color: "#696969",
            fillOpacity: 0.6,
            opacity: 0.9,
            weight: 1,
            radius: 8
        };

Это было весело! :-) Я надеюсь, что это помогает... ;-)

person Rafal Zajac    schedule 28.06.2016
comment
Спасибо, что нашли время, чтобы просмотреть мой код, я далеко, далеко не профессионал в JS, как видите... :p. Учиться, пытаясь, я думаю. Я внес предложенные вами изменения и сделал еще одно небольшое изменение в getColor(). Вызов checkTable() помещается под вызовом getArray(). Теперь все отображается на карте, хотя большой набор данных немного тормозит. Кроме того, большой набор данных не имеет цвета (странно?), и соответствующая легенда, похоже, работает неправильно. Я отредактирую свой вопрос с новыми выводами. В очередной раз благодарим за помощь. - person Jordi Z; 29.06.2016
comment
Я сделал новый вопрос, если бы вы могли взглянуть, я очень ценю это! stackoverflow.com/ вопросы/38100320/ - person Jordi Z; 29.06.2016
comment
Сегодня посмотрю, если можно :-) - person Rafal Zajac; 29.06.2016