user961346
user961346

Reputation: 301

http.jsonp and callbacks in javascript

I am working on a calculator that will consider AWS instance costs. I am pulling the data from a .js file on amazon and I would like to read it into an object but i keep getting an error "Uncaught ReferenceError: callback is not defined" .. here is my .js file.

(function() {
  var app = angular.module('formExample', []);

  var ExampleController = function($scope, $http) {
    $scope.master = {};

    $scope.update = function(user) {
      $scope.master = angular.copy(user);
      $scope.GetAws();
    };

    $scope.reset = function() {
      $scope.user = "";
    };

    function callback(data) {
      $scope.aws = data;
    }

    $scope.GetAws = function() {
      var url = "http://a0.awsstatic.com/pricing/1/ec2/linux-od.min.js?callback=callback";
      $http.jsonp(url);
    };

    $scope.reset();
  };
  app.controller('ExampleController', ['$scope', '$http', ExampleController]);
}());

Upvotes: 0

Views: 422

Answers (3)

hirra
hirra

Reputation: 977

Notice callback should be set in window scope. So,one solution is like:

$scope.reset = function() {
  $scope.user = "";
};

window.callback = function(data) {
  $scope.aws = data;
}

$scope.GetAws = function() {
  var url = "http://a0.awsstatic.com/pricing/1/ec2/linux-od.min.js?callback=callback";
  $http.jsonp(url);
};

Upvotes: 1

PSL
PSL

Reputation: 123739

It is weird that the aws link you are using supports jsonp but it does not take custom callback function name. (Atleast you can look up to find out if the query string they are looking for is callback or not). angular handles it when we provide callback=JSON_CALLBACK it gets translated to angular.callbacks_x which are exposed globally temporarily by angular to handle the request and resolve the promise accordingly. But for this the endpoint must take the callback argument and wrap the response in the same string and function invocation. However this endpoint does not seem to consider it and even without any callback it automatically wraps into default callback function invocation. So you would need to inject $window (Correct DI way) object and set callback function to it and ?callback=callback is irrelevant.

  var ExampleController = function($scope, $http, $window) {
    $scope.master = {};

    //....

    $window.callback = function(data) {
      $scope.aws = data;
    }

    $scope.GetAws = function() {
      var url = "http://a0.awsstatic.com/pricing/1/ec2/linux-od.min.js?callback=callback";
      $http.jsonp(url);
    };

    $scope.reset();
   };

   app.controller('ExampleController', ['$scope', '$http', '$window', ExampleController]);

Plnkr

Upvotes: 2

mikegertrudes
mikegertrudes

Reputation: 653

It is because the AWS script is looking to call a function called "callback" on the global scope (outside of Angular). Since your function is within the scope of another (IIFE) function, it cannot be accessed.

What I've done in a case like this is simply put the function in the global scope.

In cases where an application requires some API to have loaded before Angular can do it's magic and has a callback similar to your situation, I have done the following, manually bootstrapping Angular:

index.html

<script src="http://www.example.com/api?callback=myCallbackFunction"></script>

app.js

// callback function, in global (window) scope
function myCallbackFunction() {

  // manually bootstrap Angular
  angular.element(document).ready(function() {
    angular.bootstrap(document, ['myApp']);
  });

}


// your IIFE
(function() {

})();

Upvotes: 1

Related Questions