webdev5
webdev5

Reputation: 487

Closure with phantomJS

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();
});

Upvotes: 0

Views: 123

Answers (1)

Buzinas
Buzinas

Reputation: 11725

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);
});

Upvotes: 2

Related Questions