在订阅之外获取价值

时间:2019-07-22 20:54:11

标签: angular rxjs observable subscribe

我正在尝试使用一些值在图中显示,但是当我得到订阅函数时,返回的值是不确定的

我已经尝试放入对象数组,但仍然认为这是正确的方法,但是同样,当函数退出订阅时,值消失了。

ngOnInit() {
    this.getActiveVulForYear(2019);
    console.log(this.vulYearCount); // Here, all the values are printed correctly
    console.log(this.vulYearCount[1]);// Here, the value printed is undefined
}

getActiveVulForYear(year) {
    for (var i = 0; i <= 11; i++) {
      this.activeVulnerabilitiesByMonth(i, year)
    }
}

activeVulnerabilitiesByMonth(month, year) {
    return this.scanvulService.getScanvuls().pipe(
      map((reports: Scanvul[]) =>
        reports.filter(r => {
          this.arrayVulMonth = new Array()
          this.arrayVulMonth = r.data.split('-')
          return this.arrayVulMonth[1] == month && this.arrayVulMonth[0] == year
        }))).subscribe(
          vulsForYear => {
            this.vulsForYear = vulsForYear
            this.vulYearCount[month] = this.vulsForYear.length;            
          }
    );
}

在某个时候,我做了一个带有两个参数的对象数组:monthcount。 当我尝试打印计数时,由于某种原因参数为0。但是当我打印整个数组时,打印件会正确显示所有参数(使用正确的countmonth

有人知道如何解决此问题吗? 谢谢!

2 个答案:

答案 0 :(得分:1)

可观测对象是异步执行的,因此,如果要在它们发出值或完成值(例如日志发出的值)时执行某些操作,则必须在subscribe函数中进行操作。返回Observable的函数立即返回,而不是在Observable发出值时返回。您还应该延迟订阅而不是提前订阅。只要有可能,便可以与Observable一起使用,并且仅在您实际需要Observable中的值时(即在您要记录结果的ngOnInit中进行订阅)。

因此activeVulnerabilitiesByMonthgetActiveVulForYear应该返回Observables。订阅getActiveVulForYear中的ngOnInit,并在subscribe函数的模板中记录或设置要绑定的全局变量。

getActiveVulForYear当前还导致this.scanvulService.getScanvuls()被调用12次。如果一次对this.scanvulService.getScanvuls()的调用返回了所有数据,而您只想过滤或重新排列返回的数据,则只需提取一次数据,然后相应地filtermap

我认为这是您的代码的外观:

ngOnInit() {
  getActiveVulForYear(2019).subscribe(vulsForYear => {
    this.vulsForYear = vulsForYear;
    this.vulYearCount = vulsForYear.map(vulsForMonth => vulsForMonth.length);
    console.log(this.vulYearCount);
    console.log(this.vulYearCount[1]);
  })
}

getActiveVulForYear(year: number): Observable<Scanvul[][]> {
  return this.scanvulService.getScanvuls().pipe(
    map((reports: Scanvul[]) => {
      let vulsForYear: Scanvul[][] = Array.from({length: 12}, (v, i) => []);
      reports.forEach(r => {
        let yearMonth = r.data.split('-');
        if (yearMonth[0] == year) {
          vulsForYear[yearMonth[1]].push(r);
        }
      })
      return vulsForYear;
    })
  );
}

getActiveVulnerabilitiesByMonth(month: number, year: number): Observable<Scanvul[]> {
  return this.getActiveVulForYear(year).pipe(map(vulsForYear => vulsForYear[month]));
}

https://stackblitz.com/edit/rxjs-bvksfn

答案 1 :(得分:0)

不确定您为什么这么说

setTimeDiffStatement(time: number): string {
    const eSignatureSignedTime = time  //assuming this is a unix (epoch) timestamp with milliseconds, eg. 1563868827000
    const currentTime = moment().local();
    const timeDifference = currentTime.diff(moment(eSignatureSignedTime), "seconds");

    //Number of seconds after one week:
    const AFTER_ONE_WEEK = 604801;

    //Number of seconds between one day & one week:
    const BEFORE_ONE_WEEK = 604800;
    const AFTER_ONE_DAY = 86401;

    //Number of seconds between one hour & one week:
    const BEFORE_ONE_DAY = 86400;
    const AFTER_ONE_HOUR = 3601;

    //Number of seconds between the starting time & one hour:
    const BEFORE_ONE_HOUR = 3560;
    const STARTING_TIME = 0;

    if (timeDifference >= STARTING_TIME && timeDifference < BEFORE_ONE_HOUR) {
        return moment(eSignatureSignedTime).fromNow();
        //Outputs "15 minutes ago"
        //Documentation: https://momentjs.com/docs/#/displaying/fromnow/

    } else if (timeDifference >= AFTER_ONE_HOUR && timeDifference < BEFORE_ONE_DAY) {
        return "at " + moment(eSignatureSignedTime).format("LT");
        //Outputs "at 2:35 PM"
        //Documentation: https://momentjs.com/docs/#/parsing/string-format/

    } else if (timeDifference >= AFTER_ONE_DAY && timeDifference < BEFORE_ONE_WEEK) {
        return "on " + moment(eSignatureSignedTime).format("dddd");
        //Outputs "on Monday"
        //Documentation: https://momentjs.com/docs/#/parsing/string-format/

    } else if (timeDifference >= AFTER_ONE_WEEK) {
        return "on " + moment(eSignatureSignedTime).format("MMMM Mo");
        //Outputs "on July 10th"
        //Documentation: https://momentjs.com/docs/#/parsing/string-format/

    } else {
        return "Invalid date/time";
    }    
}

实际上,vulYearCount应该为空。

稍后,当您的scanvulService.getScanvuls()提取数据并将其传递到填充数组的管道时,数组vulYearCount就会被填充。