1

I'm getting some settings from a local JSON file. The console.log inside the function correctly logs the object, but the second after the function returns undefined, so the variable isn't being updated?

Also, within testNameSpace, this returns window, why?

namespace testNameSpace {

    let settings: any;

    function dtJSONLoad() {
        let xobj = new XMLHttpRequest();
        xobj.overrideMimeType("application/json");
        xobj.open('GET', './js/file.json', true);
        xobj.onreadystatechange = function () {
            if (xobj.readyState == 4) {
                let response = xobj.responseText;
                settings = JSON.parse(response);
                console.log(settings);
            }
        };
        xobj.send(null);
    }

    dtJSONLoad();
    console.log(settings);

}

console logs 'undefined'

console logs returned object'

Paul Redmond
  • 3,276
  • 4
  • 32
  • 52

2 Answers2

4

You are facing two of the most common issues that are being asked about in SO (at least the ones that are tagged with TypeScript).

The first is that you are making an async operation and so when you are doing this:

dtJSONLoad();
console.log(settings);

The console.log part is being executed before the dtJSONLoad has finished, and so the settings variable is undefined.
Your 2nd console.log happens when the async operation completes which is why you see the value.

The 2nd issue is the scope of this:
You are assigning a function to the xobj.onreadystatechange property, this function isn't bound to the current this so when it is executed the this is referencing the Window object.
You have two options here:

(1) Use an arrow function which saves the current scope of this:

xobj.onreadystatechange =  () => {
    // ...
};

(2) Use the Function.prototype.bind function:

xobj.onreadystatechange =  function () {
    // ...
}.bind(this);

Edit

A namespace doesn't have this, and that's because of how it's being compiled into javascript.
For example, this:

namespace mynamespace {
    console.log(this); // Error: 'this' cannot be referenced in a module or namespace body
}

Compiles into:

var mynamespace;
(function (mynamespace) {
    console.log(this);
})(mynamespace || (mynamespace = {}));

Which is equivalent of doing:

function fn() {
    console.log(this);
}

In both cases this is referencing the Window object.

If you do this however:

namespace mynamespace {
    export function fn() {
        console.log(this);
    }
}

mynamespace.fn();

It will print: Object {} which is right, and that's because the fn function resides inside mynamespace.
And the js result looks like this:

var mynamespace;
(function (mynamespace) {
    function fn() {
        console.log(this);
    }
    mynamespace.fn = fn;
})(mynamespace || (mynamespace = {}));
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
0

The Data is not there the first time you log it.

The Second time is in the callback, when the data arrived, the fist time just the second after the request started.

inetphantom
  • 2,498
  • 4
  • 38
  • 61
  • I see what you're saying, but that's not the case. If I comment out the console.log after the function, the object returns. If I comment out the one inside the function,only undefined is returned. I don't why they are logging in that order, though. – Paul Redmond Aug 25 '16 at 15:24
  • That is exactly what I am saying @PaulRedmond. Pls add some string to your logs to identify them. – inetphantom Aug 25 '16 at 15:27