Variable not defined

Hi,

I get undefined message in this code.

This is my controller code: // notations are standard

$scope.searchOutputLst=[];
$scope.searchOutputLst=MyService.retrieveData($scope.caasSearch); // this http call returns data : an array of objects
console.log($scope.searchOutputLst); // prints undefined

why its printing undefined ? what is the issue ? how to fix it ?

I am using angular js 1.3

I stab a guess at MyService.retrieveData() being an asynchronous operation.

use a callback.

yes …asynchronous operation…you are right

Here is the code : MyService

this.retrieveData = function (newSearch) {
	  $http.post(searchUrl + '/search', newSearch)
	   .then(function(result) {
	    console.log("result");
		console.log(result.data); // I get print : array of objects
		return result.data;
})};

How do I use callback in this situation ?

I need controller to wait and populate my $scope.searchOutputLst and then move on.

Will callback help me with that ?

this.retrieveData = function (newSearch) {
  return $http.post(searchUrl + '/search', newSearch)
   .then( result => result.data )
};

MyService.retrieveData($scope.caasSearch).then(function (data) {
  console.log(data)
})

You only have two options: either you use a callback, or you fire an event.

what is the alternate way to write that ? I’m not comfortable with that arrow.
Is there any way to avoid that arrow and use simple syntax ?

result => result.data is effectively the same (if you ignore how the this keyword is handled) as:

function (result) {
    return result.data;
}

okay…will try this out … will it work on angular js 1.3 ?

it will work on any Angular, as long as the browser supports JavaScript2015 or you use the babel transpiler.

All you need is JavaScript for it to work.

There are further details about arrow functions at the ES6 Arrow Functions: The New Fat & Concise Syntax in JavaScript article.

okay…checking it now …will update in 5 minutes

Not working …its printing BLANK …Here is my actual code for your convenience

controller

$scope.customerSearchOutputLst=[];
							//$scope.customerSearchOutputLst=CustomerService.retrieveSearchCustomer($scope.caasCustomerSearch);
							
							CustomerService.retrieveSearchCustomer($scope.caasCustomerSearch).then(function (data) {
								console.log(data);
								$scope.customerSearchOutputLst=data;
							})
							
							console.log("result$$$$$");
							console.log($scope.customerSearchOutputLst);  // its printing  BLANK
							

service code

this.retrieveSearchCustomer = function (newCustomerSearch) {
	  return $http.post(customerUrl + '/searchcustomer', newCustomerSearch)
	   .then(result=>result.data)
	  };

Is there anything wrong ? what I am doing wrong ?

That’s because $scope.customerSearchOutputLst still doesn’t have any value assigned to it – the $http request is still pending at that point. If you leave aside the implementation details, the the flow of events is comparable to a timeout:

var data = null;

window.setTimeout(function () {
  data = 'foo'
  console.log(1, data)
}, 1000)

console.log(2, data)

This will immediately log 2 null to the console, and only after one second 1 "foo". So all code that depends on operations inside the callback has to be in the callback as well.

As an alternative, AngularJS provides a mechanism to watch to changes of $scope properties like this (note that you have to explicitly trigger the digest-cycle though):

$scope.data = null

window.setTimeout(function () {
  $scope.data = 'foo'
  $scope.$digest()
}, 1000)

$scope.$watch('data', function () {
  console.log($scope.data) // Will first log null, and after one second "foo"
})

I can not use 1000 …because Its not possible to know the http response time.
How do you resolve this ?

You can use $q.all which is only resolved when all of the promises are resolved.

  $scope.fromThen = $q.all([
      p1.then(thenFn),
      p2.then(thenFn)
    ])
    .then(function(values) {
      console.log(values);
      return values;
    });

You can see a good example of in use at http://jsfiddle.net/ThomasBurleson/QqKuk/

1 Like

Exactly, this is why your code above doesn’t work. The timeout was just an example (a simple $http mock if you like) to demonstrate that the order of the lines of code doesn’t necessarily reflect the order in which the code is getting executed.

I could not find any example how $q can be used with $http . I need an example towards that.
this is very much confusing.

$http returns a promise, and $q.all accepts an array of promises.

okay…I’m giving it a try with $q now

I am getting inject error with $q…not able to figure it out whats wrong .

Here is the code:

Service code:

app.service('CustomerService', ['$http','$q' function ($http,$q) {
var customerUrl="some url";
this.retrieveSearchCustomer = function (newCustomerSearch) {
			var deferred = $q.defer();
			$http.post(customerUrl + '/searchcustomer', newCustomerSearch)
			.then(function(response){
			   deferred.resolve(response.data);
			})
			.catch(function(response){
			  deferred.reject(response);
			});
			return deferred.promise;
		}
}]);

Controller code:

CustomerService.retrieveSearchCustomer($scope.caasCustomerSearch).then(function(data){
	console.log("result$$$$$");
	$scope.customerSearchOutputLst= data;
	})
	.catch(function(response){
		console.log(response.status);
});

I am getting Inject error after deploy

Error:
angular.min.js:sourcemap:101 Error: [$injector:unpr] http://errors.angularjs.org/1.3.0/$injector/unpr?p0=CustomerServiceProvider%20<-%20CustomerService

whats wrong ?
also please let me know if I’m using the $q correctly in my code. …do you think any changes required ?

It looks like you’re missing a comma from the top line.