首页 > 解决方案 > 为什么我的代码的一部分没有运行,即使它在一个函数中并且它上面的打印语句有效?

问题描述

我正在运行一个角度项目,该文件将从 firebase 数据库中获取数据,getStatistics() 函数底部的代码将使用数据库包含的不同访问数据对的信息填充 map(pairArray) .

问题是 getStatistics() 函数底部的代码(由反斜杠行表示)将无法运行。好吧,for 或 if-else 循环中的任何内容都不会运行。虽然 console.log() 函数会起作用,所以我不确定为什么代码不会运行。如果我把它放在函数中更高的位置,它会运行,在所有计算百分比的数学下面。

import { Component, OnInit } from '@angular/core';

// Firestore imports 
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '@angular/fire/firestore';
import {Observable,of, from, Timestamp } from 'rxjs';
//import 'rxjs/add/operator/map';
import { map } from 'rxjs/operators';
import * as firebase from 'firebase';
import { NgForm, NgModel } from '@angular/forms';

/*
 getStatistics function:

The goal of this function is to iterate through the database and get the required statistics.
The structure of the database:
  visits IDs are stored as collections, files, in the firestore database.
  Visits of the same ID are stored as documents inside each collection.
The function iterates through each collection, ID,  and counts how many visits are stored in each ID,
 then it increments the AgencyCounter for each agency that was detected in the collection.
The iteration over collections and documents in the database is done by using the "payload.forEach" method

TODO
1. Identify group visits and exclude them from the getStatistics()
2. correct the common pair and common triplet algorithm. Agencies should be sorted based on how many times 
   they appreared in the pair or triplet visits.

 */

interface  Visit{
  code: number;
}

// interface that defines the agency visit structure
interface  AencyVisit{
  AgencyID: string;
  code: string;
  time: Timestamp<any>;
}


@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

   // Connect Agency to Firebase collection
   visitCollection: AngularFirestoreCollection<Visit>;
   visits: Observable<Visit[]>;

   // Statistics fields
  totalNumVisits = 0;
  totalMultipleVisits = 0;
  highest = 0;
   totalNumPairVisits = 0 ;
   percentageOfPairVisits = 0;
   totalNumTripletVisits = 0;
    percentageOfTripletVisits = 0;
  totalNum5PlusVisits = 0;
  lastHighest = 0;
  percentageOf5PlusVisits = 0;
  totalNum4Visits = 0;
  percentageOf4Visits = 0;
  keyHolder = "";
  valueAdjuster = 0;
  timer = null;
  k = 0;
   commonPairs = new Array();
   commonPair = new Array();
   commonTriplets = new Array();
   commonTriplet = new Array();
   values = new Array();
   //this.values.push(rand = new Array());
   //visitsy = new Array<Observable<Visit[]>>();

   agencyCounterPerID=0;
  //  counterArray ={1:0, 2:0 , 3:0}; //  key represents duplicate or triplet of agencies, value = their number
   // 32 max agency limit per visit - hopefully no one should ever reach this
   counterArray = [0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]   
   //pairArray = new Map<Array<Object>, number>(); 
   pairArray = new Map<string, number>(); 
   multiples = 0;
   //  mostCommonPairList and mostCommonTripletList will be used to filter the most common pair and triplet agencies
   mostCommonPairList = {"DEMO-B-Geese":1, "DEMO-A-Berges":1, "DEMO-C1-Gentle":1, "DEMO-C2-Crunke":1,"DEMO-C3-Girls":1, "DEMO-D-Literacy":1, "DEMO-E-Life":1,"DEMO-F-Pools":1};
   mostCommonTripletList = {"DEMO-B-Geese":1, "DEMO-A-Berges":1, "DEMO-C1-Gentle":1, "DEMO-C2-Crunke":1,"DEMO-C3-Girls":1, "DEMO-D-Literacy":1, "DEMO-E-Life":1,"DEMO-F-Pools":1};
   agencyList = new Array(); 
   IDField: Observable<any>;

   // Percentage calculations
   pctMultipleAgencyVisits: number;

  constructor(private afs: AngularFirestore) { }

  ngOnInit(): void {
    // console.log("a");
    this.getStatistics();
  }

  getStatistics(): void{
    const visitArray = this.afs.collection("visits").snapshotChanges();

    visitArray.subscribe(payload => {
      this.totalNumVisits = 0;
      this.totalNumPairVisits = 0;
      this.percentageOfPairVisits = 0;
      this.totalNumTripletVisits = 0;
      this.percentageOfTripletVisits = 0;
      this.totalNum5PlusVisits = 0;
      this.percentageOf5PlusVisits = 0;
      this.totalNum4Visits = 0;
      this.percentageOf4Visits = 0;
      const values = [];



      payload.forEach( item => {
        const visit = item.payload.doc.data() as Visit;
        //const values = [];
        this.totalNumVisits += 1;
        this.timer = null;

        // getting visited frequencies
        const visitedAgencies = this.afs.collection(visit.code.toString()).snapshotChanges();
        visitedAgencies.subscribe(payload => {


          this.agencyCounterPerID = payload.length;
          this.k = 0;
          payload.forEach( item => {
            const agencyVisit = item.payload.doc.data() as AencyVisit; 
            this.agencyList.push(agencyVisit.AgencyID);

            // Add visit pairs to nested list for later analysis
            if (this.agencyCounterPerID == 2){
                if (this.k == 0){
                    this.values.push(new Array(agencyVisit.AgencyID.toString()));
                }

                if (this.k == 1){
                    this.values[this.values.length - 1].push(agencyVisit.AgencyID.toString());
                }

                this.k = 1;
            }
          });

          console.log("list", this.agencyList.toString());

          this.counterArray[this.agencyCounterPerID]+=1;
          if (this.agencyCounterPerID == 2) {
            this.totalNumPairVisits += 1;
            var result2 = this.agencyList.includes(this.agencyList[i]);
            this.mostCommonPairList[this.agencyList[i]] += 1;
          } else if (this.agencyCounterPerID == 3) {
            this.totalNumTripletVisits += 1;
            var result3 = this.agencyList.includes(this.agencyList[i]);
            this.mostCommonTripletList[this.agencyList[i]] += 1;
          } else if (this.agencyCounterPerID == 4) {
            this.totalNum4Visits += 1;
          } else if (this.agencyCounterPerID >= 5) {
            this.totalNum5PlusVisits += 1;
          }

          for (var i=2; i<this.counterArray.length; i++) {
           this.multiples+= this.counterArray[i];
          }

          // percentages
          this.pctMultipleAgencyVisits = this.totalNumVisits / this.counterArray[2];//this.multiples;
          this.totalMultipleVisits = this.totalNumPairVisits + this.totalNumTripletVisits + this.totalNum4Visits + this.totalNum5PlusVisits;
          this.percentageOfPairVisits = this.totalNumPairVisits / this.totalMultipleVisits * 100 ;
          this.percentageOfTripletVisits = this.totalNumTripletVisits / this.totalMultipleVisits * 100;
          this.percentageOf4Visits = this.totalNum4Visits / this.totalMultipleVisits * 100;
          this.percentageOf5PlusVisits = this.totalNum5PlusVisits / this.totalMultipleVisits * 100;
          this.commonPair.push(this.agencyList[0]);
          this.commonPair.push(this.agencyList[1]);
          this.commonTriplet.push(this.agencyList[0]);
          this.commonTriplet.push(this.agencyList[0]);

          this.agencyCounterPerID =0;
          //empty the array
          this.agencyList.length = 0;

        });

    });

  });

    console.log("working");

    /////////////////////////////////////////////////////////////////////////////
    //format pairs into sorted strings
    for (let u = 0; u < this.values.length; u++){
        this.values[u].sort();
        this.values[u].toString();
        console.log("here1");
    }

    //add values to map(dictionary)
    for (let p = 0; p < this.values.length; p++){
        if (this.pairArray.has(this.values[p].toString()) == false){
            this.pairArray.set(this.values[p].toString(), 1);
            console.log("here2");
        }
        else if (this.pairArray.has(this.values[p].toString()) == true){
            //return this.pairArray;
            for (let a = 0; a < 10000; a++){
                if (this.pairArray.get(this.values[p].toString()) == a){
                    this.keyHolder = this.values[p].toString();
                    this.valueAdjuster = a + 1;

                    this.pairArray.delete(this.values[p].toString());
                    console.log("here3");
                }
                console.log("here4");
            }
            this.pairArray.set(this.keyHolder, this.valueAdjuster);
            console.log("here5");
        }
    }

    //find number of occurences of highest frequency pair
    this.highest = 0;
    for (let [key, value] of this.pairArray) {
        console.log("here7");
        if (value > this.highest){
            this.highest = value;
            console.log("here6");
        }
    }

    //add highest frequency pair to list
    for (let [key, value] of this.pairArray) {
        console.log("here9");
        if (value == this.highest && this.commonPairs.indexOf(key) == -1){
            this.commonPairs.push(key);
            console.log("here8");
            //break;
        }
    }

    //find number of occurences of second highest frequency pair
    this.lastHighest = this.highest;
    this.highest = 0;
    for (let [key, value] of this.pairArray) {
        console.log("here11");
        if (value > this.highest && value != this.lastHighest){
            this.highest = value;
            console.log("here10");
        }
    }

    //add second highest frequency pair to list
    for (let [key, value] of this.pairArray) {
        console.log("here13");
        if (value == this.highest && this.commonPairs.indexOf(key) == -1){
            this.commonPairs.push(key);
            console.log("here12");
        }
    }

    // Prints out the dictionary
    for (let [key, value] of this.pairArray) {
        console.log("here14");
        console.log("key: ", key.toString(), ", value: ", value);
    }
    console.log("end run");

    /////////////////////////////////////////////////////////////////////////////

  //console.log("values", this.values);

  // console.log(this.counterArray[1] , " visit for " , 1 , "agencies");
  // console.log(this.counterArray[2] , " visit for " , 2 , "agencies");
  // console.log(this.counterArray[3] , " visit for " , 3 , "agencies");

    //console.log("len", this.values.length);

    //console.log("counter: ", this.counterArray);



    //console.log("cp: ", typeof(this.commonPairs[0]));
    //console.log("v: ", typeof(this.values[0]));
    //console.log("values: ", this.values);

  }

  formatPercent(num) {
    return Math.round(num * 100) / 100;
  }
}

标签: angulartypescriptfirebaseloopsgoogle-cloud-firestore

解决方案


好吧,您的代码有很多内容需要吸收,但看起来底部的 for 循环在订阅之外被调用。由于这是异步代码,因此当函数运行时,for 循环中的值未定义或为空,因为您从 firebase 调用中获取的值尚未返回。当您调用 subscribe 时,代码执行继续进行,而第二个线程等待响应以执行 subscribe 内的代码。


推荐阅读