ОШИБКА TypeError: невозможно прочитать свойство _leaflet_pos, равное undefined

У меня есть приложение angular 10, использующее ngx-листовка и маршрутизацию. У меня есть компонент карты, который динамически отображает пользовательские маркеры на карте в зависимости от выбора пользователя. Я перехожу от вида компонента карты к другому компоненту. Затем я возвращаюсь к компоненту карты. Пользователь может изменить дату, и на основании этого старый слой маркеров удаляется, а новый слой маркеров загружается и отображается. Все работает нормально, но я всегда получаю такую ​​ошибку:

ERROR TypeError: Cannot read property '_leaflet_pos' of undefined
at getPosition (leaflet-src.js:2450)
at NewClass._getMapPanePos (leaflet-src.js:4439)
at NewClass._moved (leaflet-src.js:4443)
at NewClass.getCenter (leaflet-src.js:3798)
at NewClass.setZoom (leaflet-src.js:3181)
at SafeSubscriber._next (map.component.ts:960)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)

Я могу воспроизвести эту ошибку, только когда вернусь к компоненту карты. Если я остаюсь только в компоненте карты, никаких ошибок не отображается. Я искал исправление, но из того, что я обнаружил, кажется, что никто не знает, почему это происходит и как исправить эту ошибку. Я обнаружил, что эти две проблемы на GitHub связаны с той же проблемой в Vue.js, поэтому я предполагаю, что проблема связана с самой листовкой, а не с ngx-leaflet.

https://github.com/vue-leaflet/Vue2Leaflet/issues/613

https://github.com/stefanocudini/leaflet-search/issues/129

Я пытался это изменить:

  function getPosition(el) {
// this method is only used for elements previously positioned using setPosition,
// so it's safe to cache the position for performance

return el._leaflet_pos || new Point(0, 0);

}

к этому:

 function getPosition(el) {
// this method is only used for elements previously positioned using setPosition,
// so it's safe to cache the position for performance

if(el){
    return el._leaflet_pos || new Point(0, 0);
    }
    else{
    return new Point(0, 0);
    }

}

Но тогда ошибка выглядит так:

ERROR TypeError: Cannot set property '_leaflet_pos' of undefined
at setPosition (leaflet-src.js:2433)
at NewClass._resetView (leaflet-src.js:4154)
at NewClass.setView (leaflet-src.js:3174)
at NewClass.setZoom (leaflet-src.js:3186)
at SafeSubscriber._next (map.component.ts:960)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at MapSubscriber._next (map.js:35)

ОБНОВЛЕНИЕ: как @pk. предложено в комментариях, когда я не вызываю setZoom или не вызываю его перед удалением старых маркеров, я получаю эту ошибку:

ERROR TypeError: Cannot read property 'appendChild' of undefined
at NewClass._initIcon (leaflet-src.js:7608)
at NewClass._initIcon (leaflet.rotatedMarker.js:23)
at NewClass.onAdd (leaflet-src.js:7460)
at NewClass._layerAdd (leaflet-src.js:6572)
at NewClass.whenReady (leaflet-src.js:4433)
at NewClass.addLayer (leaflet-src.js:6634)
at NewClass.eachLayer (leaflet-src.js:6861)
at NewClass.onAdd (leaflet-src.js:6845)
at NewClass._layerAdd (leaflet-src.js:6572)
at NewClass.whenReady (leaflet-src.js:4433)

ОБНОВЛЕНИЕ 2: Когда я не добавляю новый слой маркеров на карту (this.deskLayer.addTo (map)), ошибка исчезает, но я хочу добавить новые маркеры на карту ... Это что происходит, когда пользователь меняет дату:

onMapReady(map: Map) {

//listening for USER DATE CHANGE
this.userFloorService.sharedUserSelectedDate
  .pipe(skip(1))
  .subscribe(() => {
    this.deskLayer.remove(); // first remove old desks
    this.userFloorService // then get desks and reservations
      .getFloor(this.floorNumber)
      .subscribe( (data) => { 
        // create new reservations
        let reservationsArr = data.records[0].reservations;
        // create new DESKS
        let deskMarkers = [];
        data.records[0].desks.forEach((desk) => {
          let deskId = desk.desk_id;
          let deskMarker = marker(
            [
              desk.desk_coordinate.coordinates[0],
              desk.desk_coordinate.coordinates[1],
            ],
            {
              title: this.getDeskTitle(desk, reservationsArr), // set desk title to RESERVED/FREE
              rotationAngle: desk.desk_angle,
              rotationOrigin: 'center center',
              riseOnHover: true
            }
          ).on('click', () => {
            this.zone.run(() => {
              this.openDeskDialog(deskMarker.options.title,deskId); 
            });
          });
          deskMarker.setIcon(this.getDeskIcon(deskMarker)); // for displaying desk icons on zoomLvl -1.5
          deskMarkers.push(deskMarker);
        });
        this.deskLayer = layerGroup(deskMarkers); // add new desks to deskLayer
        this.layersControl.overlays['Desks'] = this.deskLayer; // reassign desks in overlays for correct desk layer toggling 

        this.deskLayer.addTo(map); 
        map.setZoom(-1); // set zoom
      },
      error =>{
        console.log(error);
      }
      ); 
  });

person hawran    schedule 02.02.2021    source источник
comment
Вы вызываете setZoom до или после удаления старых маркеров? Основываясь на сообщении об ошибке, стеке и коде листовки, который вы опубликовали, я предполагаю, что старый элемент маркера уже был удален из DOM.   -  person pk.    schedule 03.02.2021
comment
@pk. Я вызываю setZoom после удаления старых маркеров. Я пытался вообще не вызывать setZoom или не вызывать setZoom перед удалением старых маркеров. Но затем он выдает ошибку appendChild of undefined, я добавил эту ошибку в свой пост в конце, чтобы вы могли ее увидеть.   -  person hawran    schedule 03.02.2021
comment
Значит, элемент на карте по какой-то причине не определен. Можете попробовать сделать демо, чтобы воссоздать это?   -  person pk.    schedule 03.02.2021
comment
Я обновил оригинальный пост некоторым кодом. Я не могу сделать демо, приложение слишком велико ...   -  person hawran    schedule 04.02.2021


Ответы (1)


Оказалось, что эти ошибки произошли из-за того, что я использовал BehaviorSubject для передачи данных между компонентами, и каждый раз, когда я переходил к компоненту карты и обратно, создавалась новая подписка на BehaviorSubject без разрушения старой подписки. Таким образом, уничтожение подписок каждый раз, когда я переходил из компонента карты, решило эту проблему. Может, это кому-нибудь поможет.

person hawran    schedule 11.02.2021