0

So I'm having trouble with getting a VAR in a function to be global, I have tried the following resources:

What is the scope of variables in JavaScript?

My previous question was marked as a duplicate but after reviewing the link above it did not help with my issue.

Here is my previous question:

So I'm using OpenTok to create a online conferencing tool and need to grab the session details from an API on a different server. I've created a php script on the other server that grabs session information based on the session id provided by a URL parameter. I know that the php script and most of the JavaScript is working correctly because when I console.log data from the parsed JSON it prints the correct information. However when I try to put the variables into the credentials area I get the following error:

ReferenceError: thesession is not defined

Here is the code used to get the JSON from a PHP script on a separate server:

var url_string = window.location.href;
var url = new URL(url_string);
var session = url.searchParams.get("s");

if (session == '') {
  window.location.replace("http://www.google.com");
}

var getJSON = function(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'json';
    xhr.onload = function() {
      var status = xhr.status;
      if (status === 200) {
        callback(null, xhr.response);
      } else {
        callback(status, xhr.response);
      }
    };
    xhr.send();
};

getJSON('http://192.168.64.2/api/meeting/?uid=' + session,
function(err, data) {
  if (err !== null) {
    console.log('Error');
  }
      var thesession = data.sessionID;
      var thetoken = data.token;
      console.log(thesession);
      console.log(thetoken);
});

let otCore;

const options = {
  credentials: {
    apiKey: "####",
    sessionId: thesession,
    token: thetoken
  },

And here is a screenshot of the console:

console

The top console log is "thesession" and the second console log is "thetoken". I have tried looking up the error but can't quite find one with the same usage as mine.

The desired outcome would be that I could using the data from the parsed JSON and use the result as the credentials e.g. data.sessionID which is bound the the VAR thesession.

I know this might be a scope issue, but I'm not sure how I could alter the code to make it work as intended.

Any help would be much appreciated, this one has really got me stumped :)

How would I alter the scope to get the desired function? I have reviewed the link that was given on the previous question, but this didn't help me with my issue.

  • 1
    Use `window.thesession` to attach the variable to the [global object](https://developer.mozilla.org/en-US/docs/Glossary/Global_object). Although use of global variables is not recommended, and in 99% of cases, unnecessary. – mario_sunny Nov 04 '19 at 11:57
  • Declare the variable at the start of your script as `var x;` (or similar), then change it in your functions like `x = ....`. Or add it to the `window` object as @mario_sunny suggests. Either way, there's probably a better way to do this than using global variables though... – James Whiteley Nov 04 '19 at 11:59
  • I get the following error when using window. "SyntaxError: unexpected token: '.'" – Daniel Faulkner Nov 04 '19 at 12:01
  • I did the following: var window.thesession = data.sessionID; – Daniel Faulkner Nov 04 '19 at 12:03
  • @DanielFaulkner `window` already exists. You just need to write `window.thesession = data.sessionID`, then reference it later with `sessionId: window.thesession`. I would recommend my approach though; explicitly modifying the window itself isn't the best move though in my opinion. – James Whiteley Nov 04 '19 at 12:06
  • Doing what you said above e.g. 'window.thesession = data.sessionID;' and 'sessionId: window.thesession' the console.log from outside the function still returns undefined – Daniel Faulkner Nov 04 '19 at 12:24
  • @JamesWhiteley I also get this error - SyntaxError: unexpected token: '.' – Daniel Faulkner Nov 04 '19 at 12:28

2 Answers2

2

var thesession = data.sessionID;

Is defined within its execution context, which is the callback function you've passed to getJSON.

One step in the right direction is to reverse the assignment. Assign 'thesession' to the options object within the scope where 'thesession' exists.

const options = {
  credentials: {
    apiKey: "####",
    sessionId: null,
    token: thetoken
  }
};

getJSON('http://192.168.64.2/api/meeting/?uid=' + session,
function(err, data) {
  if (err !== null) {
    console.log('Error');
  }
      var thesession = data.sessionID;
      var thetoken = data.token;
      console.log(thesession);
      console.log(thetoken);

      options.credentials.sessionId = thesession;
});

However, it's important to realize that your program is not going to wait for this assignment. It will send the getJSON request, and then continue processing. Your options object won't have a sessionId until the getJSON call finishes and its callback has been invoked.

This would be a good opportunity to delve into Promises, which will help you better understand how to handle the non-blocking nature of javascript.

Michael
  • 581
  • 2
  • 8
0

Your problem is that this line var thesession = data.sessionID is scoped within the function function(err, data) { ... }. In order to allow two functions to use the same variable, you need to make sure that the variable isn't declared somewhere they don't have access to.

It's the difference between this:

function func1() {
  var x = 3
}

function func2() {
  console.log(x)
}

func1();
func2();

and this:

var x;

function func1() {
  x = 3
}

function func2() {
  console.log(x)
}

func1();
func2();

Similarly, if you declare var thesession; at the start of your script (or at least outside that other function) then just set it with thesession = data.sessionID, your final part will have access to your variable thesession.


Edit

In context:

var url_string = window.location.href;
var url = new URL(url_string);
var session = url.searchParams.get("s");
var thesession;
var thetoken;

if (session == '') {
  window.location.replace("http://www.google.com");
}

var getJSON = function(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'json';
    xhr.onload = function() {
      var status = xhr.status;
      if (status === 200) {
        callback(null, xhr.response);
      } else {
        callback(status, xhr.response);
      }
    };
    xhr.send();
};

getJSON('http://192.168.64.2/api/meeting/?uid=' + session,
function(err, data) {
  if (err !== null) {
    console.log('Error');
  }
      thesession = data.sessionID;
      thetoken = data.token;
      console.log(thesession);
      console.log(thetoken);
});

let otCore;

const options = {
  credentials: {
    apiKey: "####",
    sessionId: thesession,
    token: thetoken
  },

As a side-note - I'd also recommend not using var and instead just using let of const, depending on if you want your variable to be mutable or not.

James Whiteley
  • 3,363
  • 1
  • 19
  • 46
  • Id love to try this example but im not too sure how to alter mine to fit those requirements – Daniel Faulkner Nov 04 '19 at 12:22
  • Thank you for the edit! I get the following error: Error: otAccCore: sessionId is a required credential. I tried doing a console.log(thesession); below let otCore; and it returns undefined – Daniel Faulkner Nov 04 '19 at 14:08
  • That's another issue I think... I wouldn't know without seeing more of the code. Either way, your scoping issue is fixed at least. My guess would be that you're using the variable thesession somewhere else before setting it in the getJSON function. – James Whiteley Nov 04 '19 at 16:37