0

I'm facing an unexpected situation. I have some objects(array). Those have a property break, that is boolean. break value depends upon situation, but it becomes always false when compared in if statement, in a for or for of loop. I tried to change the style of if by using ==, === and only property, but all do the same result, even when some of objects have value true. Simply saying, when the array of object is iterated, the object's break property becomes false, even if it it true. Language is TypeScript.

assume getRoute() method is called.

Following is method

import { Injectable } from '@angular/core';
import { of, EMPTY, concat } from 'rxjs';
import { HttpService } from '../http.service';
import { take, tap, map, last } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class RouteService {
  activities;
  distanceDB;
  cityFilter = [];
  route: any[];

  constructor(private httpService: HttpService) { }

  setActvities(activities) {
    this.activities = activities;
  }

  getRoute() {
    if (this.activities) {
      return concat(
          this.sortUpActivities(),
          this.calculateBreaks(),
          this.allocateNights()
        ).pipe(
          last()
        );
    }

    return EMPTY;
  }

  /* sort up activities according to city */
  private sortUpActivities() {
    const route = [];
    let counter = 0;

    for (let i = 0; i < this.activities.length; i++) {
      for (let j = 0; j < this.activities[i].length; j++) {
        const city = route.find(r => {
          return r.cityCode == this.activities[i][j].cityCode;
        });

        if (!city) {
          route[counter] = {}
          Object.defineProperty(route[counter], 'break', {
            value: false,
            writable: true
          });

          route[counter].activities = [this.activities[i][j]];
          route[counter].cityCode = this.activities[i][j].cityCode;
          counter++;
        } else {
          city.activities.push(this.activities[i][j]);
        }
      }
    }

    this.route = route;
    return of(this.route);
  }

  /* cacluate breaks required in each city */
  private calculateBreaks() {
    let timeSincePreviousBreak = 7;
    let transitTime = 0;

    return this.httpService.getCityToCity(this.cityFilter).pipe
    (
      take(1),

      tap<any[]>(cityToCity => {
        for (let i = 0; i < this.route.length; i++) {
          let totalActivityTime = 0;;
          for (const ea of this.route[i].activities) {
            totalActivityTime += ea.duration;
          }

          if (this.route[i+1]) {
            const cityToCityInfo =
              cityToCity.find(c => c.from == this.route[i].cityName
                && c.to == this.route[i+1].cityName) ||
              cityToCity.find(c => c.from == this.route[i+1].cityName
                && c.to == this.route[i].cityName);

              if (cityToCityInfo) {
                transitTime = cityToCityInfo.time || 0; // `|| 0` because of DB probable problem
              } else {
                transitTime = 0; // `|| 0` because of probable DB problem
              }
          } else {
            transitTime = 0; // because it is perhapse last city
          }

          const totalTime = timeSincePreviousBreak + totalActivityTime + transitTime;

          this.route[i].activityTime = totalActivityTime;
          if (totalTime >= 9) {
            this.route[i].break = true;
            timeSincePreviousBreak = transitTime;
          } else {
            this.route[i].break = false;
            timeSincePreviousBreak = totalTime;
          }
        }
      }),

      map(cityToCity => { return this.route })
    );
  }


  /* allocate nights according to breaks */
  private allocateNights() {
    for (let i = 0; i < this.route.length; i++) {
      if (this.route[i].break) {
        Object.defineProperty(this.route[i], 'nights', {
          value: 0,
          writable: true
        });

        if (this.route[i].activityTime <= 7) {
          this.route[i].nights = 1;
        } else if (this.route[i].activityTime <= 14) {
          this.route[i].nights = 2;
        } else {
          this.route[i].nights = 3;
        }
      } else {
        console.log(this.route[i].break);
      }
    }

    return of(this.route);
  }
}

Following is the log

Angular is running in the development mode. Call enableProdMode() to enable the production mode. core.js:38781
(5) […]
​
0: {…}
​​
activities: Array [ {…} ]
​​
activityTime: 3
​​
break: true
​​
cityCode: "ELL"
​​
<prototype>: Object { … }
​
1: {…}
​​
activities: Array [ {…} ]
​​
activityTime: 5
​​
break: false
​​
cityCode: "NUW"
​​
<prototype>: Object { … }
​
2: {…}
​​
activities: Array [ {…}, {…} ]
​​
activityTime: 10
​​
break: true
​​
cityCode: "KAN"
​​
<prototype>: Object { … }
​
3: {…}
​​
activities: Array [ {…} ]
​​
activityTime: 5
​​
break: false
​​
cityCode: "YAL"
​​
<prototype>: Object { … }
​
4: {…}
​​
activities: Array(3) [ {…}, {…}, {…} ]
​​
activityTime: 12
​​
break: true
​​
cityCode: "GAL"
​​
<prototype>: Object { … }
​
length: 5
​
<prototype>: Array []
route.service.ts:118:12

----------------------------------------------------
false 5 route.service.ts:135:16
----------------------------------------------------
(5) […]
​
0: {…}
​​
activities: Array [ {…} ]
​​
activityTime: 3
​​
break: true
​​
cityCode: "ELL"
​​
<prototype>: Object { … }
​
1: {…}
​​
activities: Array [ {…} ]
​​
activityTime: 5
​​
break: false
​​
cityCode: "NUW"
​​
<prototype>: Object { … }
​
2: {…}
​​
activities: Array [ {…}, {…} ]
​​
activityTime: 10
​​
break: true
​​
cityCode: "KAN"
​​
<prototype>: Object { … }
​
3: {…}
​​
activities: Array [ {…} ]
​​
activityTime: 5
​​
break: false
​​
cityCode: "YAL"
​​
<prototype>: Object { … }
​
4: {…}
​​
activities: Array(3) [ {…}, {…}, {…} ]
​​
activityTime: 12
​​
break: true
​​
cityCode: "GAL"
​​
<prototype>: Object { … }
​
length: 5
​
<prototype>: Array []
route.service.ts:139:12
Ahmad Raza
  • 129
  • 2
  • 13
  • 1
    Is `this.route` filled in asynchronously? Also, that log doesn't tell me much - I don't know which value comes from which `console.log` statement – VLAZ Feb 21 '20 at 10:29
  • @VLAZ Please note ---- in the log, that is log seperator. First is before loop, second is after loop. `false 5` is inside loop. – Ahmad Raza Feb 21 '20 at 10:32
  • @VLAZ this.route is filled async, but that does not affect, since I'm using `concat` of observable. And this method is called, after the value filler method is called. Also, if async affect, why the log at top have values true. – Ahmad Raza Feb 21 '20 at 10:34
  • 1
    The [console is lazy](https://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays), so you'd see the *latest* state the object is in. This is not necessarily the state when the loop executed. – VLAZ Feb 21 '20 at 10:36
  • @VLAZ now added complete class, please review. – Ahmad Raza Feb 21 '20 at 10:42
  • Best way is to put debugging points in browser dev tool at all assignment lines . And see whats causing it. It wont take much time – Shashank Vivek Feb 21 '20 at 11:02

0 Answers0