浏览代码

🐛 safely handle not-yet-loaded layers

jmacura 4 年之前
父节点
当前提交
7f39bc97f8
共有 1 个文件被更改,包括 89 次插入66 次删除
  1. 89 66
      src/adjuster/adjuster.service.ts

+ 89 - 66
src/adjuster/adjuster.service.ts

@@ -27,12 +27,7 @@ export class AdjusterService {
   factors = [];
   factors = [];
   numberOfClusters: number;
   numberOfClusters: number;
   //method: string;
   //method: string;
-  methods: Array<{
-    codename: string;
-    layer?: VectorLayer;
-    name: string;
-    type: string;
-  }>;
+  methods: Array<MethodDescription>;
   private _clusteringInProcess: boolean;
   private _clusteringInProcess: boolean;
   private _clustersLoaded: boolean;
   private _clustersLoaded: boolean;
   private _loadInProcess: boolean;
   private _loadInProcess: boolean;
@@ -110,34 +105,8 @@ export class AdjusterService {
         attractivenessData.forEach((a) => {
         attractivenessData.forEach((a) => {
           codeRecordRelations[a.code] = a;
           codeRecordRelations[a.code] = a;
         });
         });
-        let errs = 0;
-        //let logs = 0;
         console.time('forEach-Index');
         console.time('forEach-Index');
-        obce.forEachFeature((feature) => {
-          // Pair each feature with its attractivity data
-          const featureData = codeRecordRelations[feature.get('nationalCode')];
-          if (!featureData) {
-            if (errs < 20) {
-              errs++;
-              console.warn(
-                `No data for feature ${feature.get('nationalCode')}`
-              );
-              console.log(feature);
-            }
-            return;
-          }
-          /*logs++;
-          if (logs % 100 == 0) {
-            console.log(`processed ${logs} items`);
-          }*/
-          Object.keys(featureData).forEach((key, index) => {
-            if (key !== 'lau2') {
-              feature.set(key, featureData[key], true); //true stands for "silent" - important for performance!
-            }
-          });
-        });
-        // Since we are updating the features silently, we now have to refresh manually
-        obce.getFeatures()[0].dispatchEvent('change');
+        this.processIndex(codeRecordRelations);
         console.timeEnd('forEach-Index');
         console.timeEnd('forEach-Index');
         this._raiInProcess = false;
         this._raiInProcess = false;
         this.adjusterEventService.loaded.next({
         this.adjusterEventService.loaded.next({
@@ -175,8 +144,6 @@ export class AdjusterService {
       .toPromise()
       .toPromise()
       .then((data: any) => {
       .then((data: any) => {
         console.log('data received', data);
         console.log('data received', data);
-        //let logs = 0;
-        let errs = 0;
         const clusterData = data.response;
         const clusterData = data.response;
         // Store relation between region and its data in a hash-table-like structure
         // Store relation between region and its data in a hash-table-like structure
         // more memory consuming, but much faster then find()
         // more memory consuming, but much faster then find()
@@ -208,38 +175,9 @@ export class AdjusterService {
           }*/
           }*/
         console.time('forEach-Cluster');
         console.time('forEach-Cluster');
         for (const method of this.methods) {
         for (const method of this.methods) {
-          method.layer.getSource().forEachFeature((feature) => {
-            // Pair each feature with its clustering data
-            const featureData =
-              codeRecordRelations[feature.get('nationalCode')];
-            /*const featureData = clusterData.find(
-              // NOTE: Do NOT add triple equal sign!
-              (item) => item['lau2'] == feature.get('nationalCode')
-            );*/
-            if (!featureData) {
-              if (errs < 20) {
-                errs++;
-                console.warn(
-                  `No data for feature ${feature.get('nationalCode')}`
-                );
-                console.log(feature);
-              }
-              return;
-            }
-            /*logs++;
-            if (logs % 100 == 0) {
-              console.log(`processed ${logs} items`);
-            }*/
-            feature.set(method.codename, featureData[method.codename], true);
-            /*Object.keys(featureData).forEach(function (key, index) {
-              if (key !== 'lau2') {
-                feature.set(key, featureData[key], true);
-              }
-            });*/
-          });
-          // Since we are updating the features silently, we now have to refresh manually
-          method.layer.getSource().getFeatures()[0].dispatchEvent('change');
+          this.processClusters(method, codeRecordRelations);
         }
         }
+        // Another implementation of the loop above, yet too slow
         //const clusters = [];
         //const clusters = [];
         //const obceFeatures: Array<any> = obce.getFeatures();
         //const obceFeatures: Array<any> = obce.getFeatures();
         // Array of arrays
         // Array of arrays
@@ -340,6 +278,84 @@ export class AdjusterService {
       });
       });
   }
   }
 
 
+  processIndex(codeRecordRelations: Record<string, unknown>): void {
+    if (obce.getState() !== 'ready') {
+      obce.once('featuresloadend', () =>
+        this.processIndex(codeRecordRelations)
+      );
+      return;
+    }
+    let errs = 0;
+    //let logs = 0;
+    obce.forEachFeature((feature) => {
+      // Pair each feature with its attractivity data
+      const featureData = codeRecordRelations[feature.get('nationalCode')];
+      if (!featureData) {
+        if (errs < 20) {
+          errs++;
+          console.warn(`No data for feature ${feature.get('nationalCode')}`);
+          console.log(feature);
+        }
+        return;
+      }
+      /*logs++;
+      if (logs % 100 == 0) {
+        console.log(`processed ${logs} items`);
+      }*/
+      Object.keys(featureData).forEach((key, index) => {
+        if (key !== 'lau2') {
+          feature.set(key, featureData[key], true); //true stands for "silent" - important for performance!
+        }
+      });
+    });
+    // Since we are updating the features silently, we now have to refresh manually
+    obce.getFeatures()[0].dispatchEvent('change');
+  }
+
+  processClusters(
+    method: MethodDescription,
+    codeRecordRelations: Record<string, unknown>
+  ): void {
+    if (method.layer?.getSource().getState() !== 'ready') {
+      method.layer
+        .getSource()
+        .once('featuresloadend', () =>
+          this.processClusters(method, codeRecordRelations)
+        );
+      return;
+    }
+    let errs = 0;
+    //let logs = 0;
+    method.layer.getSource().forEachFeature((feature) => {
+      // Pair each feature with its clustering data
+      const featureData = codeRecordRelations[feature.get('nationalCode')];
+      /*const featureData = clusterData.find(
+        // NOTE: Do NOT add triple equal sign!
+        (item) => item['lau2'] == feature.get('nationalCode')
+      );*/
+      if (!featureData) {
+        if (errs < 20) {
+          errs++;
+          console.warn(`No data for feature ${feature.get('nationalCode')}`);
+          console.log(feature);
+        }
+        return;
+      }
+      /*logs++;
+      if (logs % 100 == 0) {
+        console.log(`processed ${logs} items`);
+      }*/
+      feature.set(method.codename, featureData[method.codename], true);
+      /*Object.keys(featureData).forEach(function (key, index) {
+        if (key !== 'lau2') {
+          feature.set(key, featureData[key], true);
+        }
+      });*/
+    });
+    // Since we are updating the features silently, we now have to refresh manually
+    method.layer.getSource().getFeatures()[0].dispatchEvent('change');
+  }
+
   clustersLoaded(): boolean {
   clustersLoaded(): boolean {
     return this._clustersLoaded;
     return this._clustersLoaded;
   }
   }
@@ -365,3 +381,10 @@ export class AdjusterService {
     return this._raiInProcess;
     return this._raiInProcess;
   }
   }
 }
 }
+
+type MethodDescription = {
+  codename: string;
+  layer?: VectorLayer;
+  name: string;
+  type: string;
+};