angular - 为什么我的代码的一部分没有运行,即使它在一个函数中并且它上面的打印语句有效?
问题描述
我正在运行一个角度项目,该文件将从 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;
}
}
解决方案
好吧,您的代码有很多内容需要吸收,但看起来底部的 for 循环在订阅之外被调用。由于这是异步代码,因此当函数运行时,for 循环中的值未定义或为空,因为您从 firebase 调用中获取的值尚未返回。当您调用 subscribe 时,代码执行继续进行,而第二个线程等待响应以执行 subscribe 内的代码。
推荐阅读
- perl - Perl - 具有修改数据的新哈希项,来自另一个条目的馈线哈希,破坏了第一个条目
- javascript - 在使用 Golang 中的 Otto 解释的 JavaScript 中访问 SQLite
- xcode - 如何在 Xcode 中以 Apple watch 数字表冠的度数旋转
- javascript - 使用 jQuery 创建暂停和恢复圆形动画
- html - 使用 height 属性设置 IFrame 高度,忽略 CSS 规则
- reactjs - 如何渲染在 React 中作为子级传递的 JSX?
- java - 无法为表连接映射平面对象
- xml - 如何使用 XML::XPath 获取属性?
- reactjs - 允许与开放模式交互(React 和 Material UI)
- python - python字符串去除字符