0

I'm using phantomJS to populate data from a service. In the code below sessionToken is set but I can't access it outside of the function scope. I know I need to use a closure but I haven't been able to get it to work. How do I write a closure so I can access the variable outside of the scope?

var url = "https://securitybeta.srsplatform.com/WebServices/Srs.WebPlatform.WebServices.SrswpSite.SessionTokenService.svc/JSON/ISessionTokenServiceV2/CreateSessionToken?username=srsCore&password=[redacted]";

var page = require('webpage').create();

page.onResourceError = function(resourceError) {
        console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
        console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};

var sessionToken = 0;

var getSessionToken = page.open(url, 'get', function(status) {
    sessionToken = page.plainText;
    sessionToken = JSON.parse(sessionToken);
    sessionToken = sessionToken.Item.AuthorizedSessionToken;

    console.log('Status: ' + status + ' sessionToken = ' + sessionToken);
    //console.log(sessionToken);
    return function () {
        return sessionToken;
    }

});
sessionToken = getSessionToken();
console.log('sessionToken outside of function scope: ' + sessionToken);

sessionToken will be used in the following code:

 var webPage = require('webpage');
var vehiclePage = webPage.create();
var settings = {
    operation: "POST",
    encoding: "utf8",
    headers: {
        "Content-Type": "application/json"
    },
    data: JSON.stringify({
        "VIN": "JF2SJAAC5EG432990",
        "StandardIds": null,
        "LicenseCountry": null,
        "LicensePlate": "334 142",
        "LicenseState": "UT",
        "OdometerUnitOfMeasure": 0,
        "UnitNumber": null,
        "Year": 1994,
        "Make": "Chevrolet",
        "Model": "Camaro",
        "Engine": null,
        "Color": null,
        "Description": null
    })
};

vehiclePage.onResourceError = function(resourceError) {
    console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
    console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};

vehiclePage.open("https://ws-smsbeta.srsplatform.com/api/v1/Vehicle/Save?sessionToken=" + sessionToken + "&shopId=" + SHOP_ID, settings, function(status) {
    var vehicleGuid = vehiclePage.plainText;
    console.log('Status: ' + status + " " + vehicleGuid);
    phantom.exit();
});
webdev5
  • 467
  • 1
  • 8
  • 22
  • 1
    Either I'm missing something or I'm stating the obvious here, But, did you try and set sessionToken outside of page.open's callback ? – elad.chen Sep 18 '15 at 22:06
  • Setting it ouside of the page.open doesn't work. – webdev5 Sep 18 '15 at 22:12
  • 1
    Related: [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) Answer: It's not possible. – Artjom B. Sep 18 '15 at 22:56

1 Answers1

2

First of all, if you want to use the variable outside the annonymous function, you must declare it before.

var sessionToken = {};

page.open(url, 'get', function(status) {
    sessionToken = page.plainText;
    sessionToken = JSON.parse(sessionToken);
    sessionToken = sessionToken.Item.AuthorizedSessionToken;

    console.log('Status: ' + status + ' sessionToken = ' + sessionToken);
    //console.log(sessionToken);

});

console.log('sessionToken outside of function scope: ' + sessionToken);

But you must understand that the page.open method is asynchronous, and that the last line of the code above will execute before the first line of the annonymous function passed to it. That function will be called only after the url is got, so, you can use the .plainText of it.

If you try to use the .plainText outside the function, after calling the page.open method, you'll have the same problem, as soon as it was not loaded yet.


Update

After your editions, you must put the other code inside a function, for example:

function loadVehicle(sessionToken) {
  var webPage = require('webpage');
  var vehiclePage = webPage.create();
  var settings = {
      operation: "POST",
      encoding: "utf8",
      headers: {
          "Content-Type": "application/json"
      },
      data: JSON.stringify({
          "VIN": "JF2SJAAC5EG432990",
          "StandardIds": null,
          "LicenseCountry": null,
          "LicensePlate": "334 142",
          "LicenseState": "UT",
          "OdometerUnitOfMeasure": 0,
          "UnitNumber": null,
          "Year": 1994,
          "Make": "Chevrolet",
          "Model": "Camaro",
          "Engine": null,
          "Color": null,
          "Description": null
      })
  };

  vehiclePage.onResourceError = function(resourceError) {
      console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
      console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
  };

  vehiclePage.open("https://ws-smsbeta.srsplatform.com/api/v1/Vehicle/Save?sessionToken=" + sessionToken + "&shopId=" + SHOP_ID, settings, function(status) {
      var vehicleGuid = vehiclePage.plainText;
      console.log('Status: ' + status + " " + vehicleGuid);
      phantom.exit();
  });
}

And then, inside the annonymous function passed to the page.open method:

page.open(url, 'get', function(status) {
    sessionToken = page.plainText;
    sessionToken = JSON.parse(sessionToken);
    sessionToken = sessionToken.Item.AuthorizedSessionToken;
    loadVehicle(sessionToken);
});
Buzinas
  • 11,597
  • 2
  • 36
  • 58
  • Please see my edit. I'm not sure how to integrate your solution. – webdev5 Sep 18 '15 at 22:29
  • @webdev5 I can't understand your edit. Please, copy your full code, and show us what you're trying to accomplish, so I can help you out with your exact problem. – Buzinas Sep 18 '15 at 22:37
  • Ok how's that? I had to redact the password for security reasons. – webdev5 Sep 18 '15 at 22:41
  • @webdev5 Your code still say nothing. Why you must use the `sessionToken` outside the closure? You didn't paste the code showing how you want to use it. – Buzinas Sep 18 '15 at 22:45