Home > other >  Angular - TypeError: Cannot read properties of undefined (reading 'reduce)
Angular - TypeError: Cannot read properties of undefined (reading 'reduce)

Time:10-31

When I try to execute this block of code this is what I get.

Line 82 where the error happens is: var group = this.detailsDate.reduce(function (r, o){

core.js:6486 ERROR TypeError: Cannot read properties of undefined (reading 'reduce') at DashboardComponent.getDatesOnly (dashboard.component.ts:82) at DashboardComponent.ngOnInit (dashboard.component.ts:56)

 getDatesOnly(){
       this.requestService.getAllRequests().subscribe(data=>{
         JSON.stringify(data);
         this.requestAllDetails=data
          var alldates = this.requestAllDetails.map(t=>t.startDate)
           this.detailsDate = alldates;
          console.log(alldates)
     })
     //above code returns array containing dates only
     

     //returns array with month   count
     var monthNames = [
         "January", "February", "March",
         "April", "May", "June",
         "July", "August", "September",
         "October", "November", "December"
     ];

     var group = this.detailsDate.reduce(function (r, o){
         var date = new Date(o);
         var month = date.getMonth();
         var monthName = monthNames[month];
         (r[monthName]) ? r[monthName].count   : r[monthName] = { monthName: monthName, count: 1 };
         return r;
     }, {});

     var result = Object.keys(group).map((key) => group[key]);

     console.log(result);

 }

CodePudding user response:

// Top of your file
const monthNames = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December"
];

class YourComponent ... {
  getDatesOnly(){
    this.requestService
    .getAllRequests()
    .subscribe(data => {
      this.requestAllDetails = [...data] // You didn't specified but i pretend this is an array
      const alldates = this.requestAllDetails.map(t => t.startDate)
      this.detailsDate = allDates.reduce(function (r, o){
         const date = new Date(o);
         const month = date.getMonth();
         const monthName = monthNames[month];
         (r[monthName]) ? r[monthName].count   : r[monthName] = { monthName: monthName, count: 1 };
         return r;
      }, {});
      const result = Object.keys(this.detailsDate).map((key) => group[key]);
      console.log(result);
    });
 }

The subscribe method is asyncronous, meaning that your code first execute the reduce and only then the subscribe callback

CodePudding user response:

The reason you're getting this error because the detailsDate get's populated with data in a subscribe method, meaning that this code is not synchronous.

The observer pattern is a software design pattern adapted in Angular which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes. This pattern is actually very similar to the publish/subscribe design pattern (usually implemented in servers via message queues like Kafka or Azure service bus).

Observables are declarative meaning that, you define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes (or until they unsubscribe).

Subscriptions are used to handle async method calls. Thus, the code inside the subscribe() method is executed only when the async method return its result (after a http call for instance). While waiting for the async response, the program continues and execute the following code and this is why your code is not working as you might expect.

You can move the reduce logic to the subscribe to get it working.

getDatesOnly(){
       var monthNames = [
         "January", "February", "March",
         "April", "May", "June",
         "July", "August", "September",
         "October", "November", "December"
     ];
          
       this.requestService.getAllRequests().subscribe(data=>{
         JSON.stringify(data);
         this.requestAllDetails=data
          var alldates = this.requestAllDetails.map(t=>t.startDate)
           this.detailsDate = alldates;
          console.log(alldates)
          
         var group = this.detailsDate.reduce(function (r, o){
         var date = new Date(o);
         var month = date.getMonth();
         var monthName = monthNames[month];
         (r[monthName]) ? r[monthName].count   : r[monthName] = { monthName: monthName, count: 1 };
         return r;
     }, {});

     var result = Object.keys(group).map((key) => group[key]);
     console.log(result);
     })


 }
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

More about observables and subscribers can be found here - https://angular.io/guide/observables

  • Related