0

I hope to be clear in my first question here.

I was trying to perform a sort on the exhibitors array and while troubleshooting I got these confusing logs in the console.

When I am console logging an array it shows the list of objects but logging an element of any index of the same array shows undefined.

I am aware of the nested subscriptions, there is an API flaw that will be fixed.

I got half an answer from work, I am trying to sort that array before the subscription ends, asynchronous behaviour I presume. So if I move the sorting method into the subscription after the exhibitor list gets built, the problem is solved.

One question remains, why the confusing logs in the console. If the subscription didn't end, shouldn't we get undefined for all? This made it so hard to debug.

Bellow is the context, method in an Angular component.

listExhibitors() {
    this.listEx$ = this.exhibitorService.list().subscribe((res) => {
        this.allExhibitors = res;
        this.exhibitors = [];
        this.exhibitorsFiltered = []
        this.userId = this.auth.getUserId();
        for (let exhib of this.allExhibitors) {
            this.exhibitorService.get(exhib.idx).subscribe((res2: any) => {
                let members = res2.members
                members.forEach(member => {
                    if (member.userIdx === this.userId) {
                        console.log('Pushin user..')
                        this.exhibitors.push(exhib)
                    }
                })
            });
        }
        console.log(this.exhibitors) // logs in the console an array of objects
        console.log(typeof (this.exhibitors)) // Object
        console.log(this.exhibitors[0]) // undefined

        this.exhibitorsFiltered = this.exhibitors.sort(function (a, b) {
            return ((a.name < b.name) ? -1 : ((a.name > b.name) ? 1 : 0));
        })

        console.log(this.exhibitorsFiltered) // logs in the console same array of objects
        console.log(this.exhibitorsFiltered[0]) // undefined
    })
}

First five logs are from the snippet in that order, the last one is console.log(typeof (this.exhibitorService.list()))

more descriptive logs

this is the code that works:

listExhibitors() {
    this.listEx$ = this.exhibitorService.list().subscribe((res) => {
        this.allExhibitors = res;
        console.log(res)
        this.exhibitors = [];
        this.exhibitorsFiltered = []
        this.userId = this.auth.getUserId();
        for (let exhib of this.allExhibitors) {
            this.exhibitorService.get(exhib.idx).subscribe((res2: any) => {
                let members = res2.members
                members.forEach(member => {
                    if (member.userIdx === this.userId) {
                        this.exhibitors.push(exhib)
                    }
                })
                this.exhibitorsFiltered = this.exhibitors.sort((a, b) => {
                    //handle null cases
                    if (!a && !b) { return 0; }
                    if (!a) { return 1; }
                    if (!b) { return -1; }
                    //both not null do actual compare
                    return a.name.localeCompare(b.name, navigator.languages[0]
                        || navigator.language, { numeric: true, ignorePunctuation: true });
                });
            });
        }
    });
}

1 Answers1

0

The callback passed into subscribe is likely happening on a different process tick -- that's generally how callbacks happen in node.

console.log(this.exhibitors) is happening before any of the elements within the subscribe function get added.

If you were to put a console.log each time you push, something like:

if (member.userIdx === this.userId) {
  console.log('Pushing user');
  this.exhibitors.push(exhib)
}

You'll likely see that you get the empty array first, followed by the pushes.

The way to fix that will depend on what exactly you're trying to do, but it should be the case that your array is being populated. You might see it if you were to do:

setTimeout(() => {
  console.log(this.exhibitors);
}, 5000);
Matt
  • 344
  • 1
  • 5
  • I am getting the 'pusher user' logs after the array but the array is populated, list of objects. Now why is this happening while if I try console.log(this.exhibitors[0]) returns undefined? – Morrison7252 Jun 17 '22 at 13:34
  • The code you have is asynchronous -- the `subscribe` callback is called at a later time (maybe just a few milliseconds later, but still not _synchronously_). Here's a [short article](https://nodejs.org/en/knowledge/getting-started/control-flow/what-are-callbacks/) from Nodejs.org briefly describing the concept. Reading more on callbacks and asynchronous control flow may be helpful for you. – Matt Jun 17 '22 at 13:47