FrostyFire
FrostyFire

Reputation: 3258

Node.JS Recursive Function Bad Variable

I am having a weird issue where if I hardcode a variable, my code works. When the code sets the variable I get weird results. However using console log I can see that the variable IS the correct value. I can literally copy the console value and paste it in place of the variable, and it will work.

function CheckInboxes (boxes, count=0) {
    console.log('-----------------------------------------')
    console.log('checking: ' + boxes[count] + ' | ' + count)
    console.log('-----------------------------------------')

    OpenInbox(boxes[count]).then(box => { //If I set this to 0 or any other value count would be, it works.

        console.log('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^')
        console.dir(box)
        console.log('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^')


        if(count < boxes.length -1) {
            var test = count + 1
            CheckInboxes(boxes, test) }
        else
            console.log('FINISHED<<<<<<<<<<<<<<<<<<<<<<<<<<')


    })


}

boxes is an array of mailbox names ie "inbox", "draft", "etc"

The OpenInbox function returns an object defining that inbox (folder). This includes the name. The name should match the first parameter. So OpenInbox('inbox') returns an object with a name property of "inbox" because the library searches for a folder with that name and returns the object associated with it.

The problem is, this is not what happens if its not hardcoded. Its completely random. The returned object could be draft or any other folder. Sometimes it happens to be the right folder.

> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> ----------------------------------------- checking: Inbox | 0
> ----------------------------------------- opening...Inbox

This clearly shows its 0 and its passing "Inbox". The result will be random though. HOWEVER, if I replace

OpenInbox(boxes[count])

with

OpenInbox(boxes[0]) //or just 'inbox' 

It works. Of course this isn't practical...

So I am very confused. Console clearly shows whats being passed, yet it doesn't work unless I hardcode the value outputted in console. This shouldn't be possible. Am I missing something?

UPDATE:

So by accident I add this code:

console.dir(box)
        console.log(box.name)
        console.log(JSON.stringify(box))

The result is...

enter image description here

Notice the underlined parts are completely different.

This leads me to think its a bug in chrome console.log or something because stringify shows the data I'm expecting.

Upvotes: 0

Views: 201

Answers (2)

jfriend00
jfriend00

Reputation: 707556

To make promises work properly with recursion and keep the chain in order, you need to return the inner promises so everything is properly chained together. Note the places where I added return:

function CheckInboxes (boxes, count=0) {
    console.log('-----------------------------------------')
    console.log('checking: ' + boxes[count] + ' | ' + count)
    console.log('-----------------------------------------')

    // return this promise
    return OpenInbox(boxes[count]).then(box => {

        console.log('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^')
        console.dir(box)
        console.log('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^')

        if(count < boxes.length -1) {
            // return this promise
            return CheckInboxes(boxes, count + 1);
        } else {
            console.log('FINISHED<<<<<<<<<<<<<<<<<<<<<<<<<<');
            // Is there a proper value to return here?
        }
    });
}

The way you had it, you were creating new independent promise chains which would interleave with each other rather than run serially.


P.S. There are some known issues with console.log(obj) in Chrome. If you immediately change obj right after you do console.log(obj), then Chrome might not output what you wanted. It appears that the obj is not immediately copied and the console.log() is not immediately carried out (perhaps because of process boundaries) so if you immediately modify obj, it might get changed before console.log() actually does its work. The usually work-around when you see this happening is exactly what you did (use JSON.stringify()). Fortunately, this doesn't happen that frequently, but when it does it can be very confusing. I'm just very careful in my code to notice if I'm immediately modifying an object that I just output with console.log() and, if so, I either output just the desired property or I use JSON.stringify().

Upvotes: 2

aifarfa
aifarfa

Reputation: 3939

the boxes could be an object not array. check your boxes with Object.keys(boxes)

if it's string or number ..

{
  "0": {..},
  "1": {..},
}
// OR
{
  0: {..},
  1: {..},
  ...
}

Upvotes: 1

Related Questions