ReferenceError message in javascript? - javascript

Why am i getting the following error:ReferenceError: result is not defined"
function returnData() {
_myService.getData().then(function(data) {
var result = data;
});
return result;
}

Because result is declared within the callback you passed into then. It doesn't exist outside.
You can declare it outside, but note that it won't have the data as of your return result; line later:
function returnData(){
var result; // <==== Note
_myService.getData().then(function(data){
result = data; // <==== No `var` here
})
// WON'T HAVE THE VALUE HERE, it's too soon
return result;
}
See How do I return the response from an asynchronous call? for why, and what to do about it. Basically, you don't need the returnData function at all, it doesn't add any value (other than perhaps encapsulation around _myService). It cannot return the value. So either use _myService directly, or if you're trying to hide that, just
function returnData() {
return _myService.getData();
}
...and use then in the calling code to receive it. Since again, returnData can't return the data.

#Yosvel's answer is correct, the reason is because you are making an Asynchronous call to your service.
In doing so, you must wait for a result to be returned to you, which can then be processed in your then function.
By having two return calls, your return value is undefined because it is not waiting for the callback function, but simply returning a null value.

I suppose that calling _myService.getData() you are making an Asynchronous call to a web service..
In that case you can return your service response data like this:
function returnData() {
return _myService
.getData()
.then(function(data) {
// Here you can work with the response data
return data;
});
}
Notice that you can work with the response in the callback, as you correctly passed into then.

Related

How to set variable value with a promise

I'm stuck figuring how set a variable value (ex. response of an ajax call) using promises.
I have for instance:
something.value = getVariable('id'); // { id : 'Adam Smith' }
where
getVariable(id) {
return $.ajax({
//...
}).done(function(response) {
//... getVariable return response
}).fail(function(response) {
//... getVariable return something_else
});
// ...
getVariable should change from promise to ajax (or any other asynchronous) response value once done().
You can't directly set a variable the way you're trying to do it. Because your operations are async, the only place you can reliably use the result of your async operations is inside the promise handlers such as .done() or .then(). So, setting the result into some variable and then expecting to use that variable in other code usually won't work properly. It will usually result in timing issues.
Instead, you have to learn to program with asynchronous results where you actually USE the variable inside the promise handler callback. You don't store it and then expect to use it in other code.
function getVariable(id) {
return $.ajax({...});
});
getVariable(...).then(function(response) {
// process result here
// don't just store it somewhere and expect other code to use that stored
// value. Instead, you use the result here and put whatever code
// needs that value in here.
}, function(err) {
// handle error here
});

How to make $http.get return response instead of promise object?

var final;
final = $http.get('http://localhost:9000/therapist_data',config)
.success(function(response) {
console.log("I got the data I requested");
var resdata = response;
console.log(resdata);
return resdata;
});
console.log(final);
I am trying to return response data and store it into final variable instead I am getting the promise object.
How do I return actual data?
I'll try to develop Cyril answer based on your code :
var final;
final = $http.get('http://localhost:9000/therapist_data',config)
.success(function(response) {
console.log("I got the data I requested");
var resdata = response;
console.log(resdata);
return resdata;
});
console.log(final);
Here is the order of execution :
var final
$http.get('http://localhost:9000/therapist_data',config)
.success(); : this will trigger the request and register the function in success as a callback when server will have respond to your request
console.log(final); -> so still undefined. It does NOT WAIT for the response.
some times later ... your function in the success is called.
This is the very basis of callbacks and asynchonous processing, you don't know when it will be executed, or at least, it will often be executed after all the other code. In angularJS there is no way of doing a synchronous request. You must move you code in the success function.
As long as you are making a network call, your data will return back asynchronously, it is the nature of it, you can't fight it.
var wrongFinal; // <-- nope, final will never get into that scope
$http.get('http://localhost:9000/therapist_data',config)
.success(function(response) {
console.log("I got the data I requested");
var goodFinal = reponse; // <-- yes, here, the data lived
// do something with the data here
});
console.log(wrongFinal); // nop, wrong scope, no sense, data doesn't live here
Soooooo, the answer is a question:
What do you want to do with your data?
It depends on the destination. Are you going to make anoher network call? Do you want to update the view? Do you want to call a 3rd party library?
You need to understand and to embrace the nature of asynchronous in JavaScript.
$http.get will always return a promise.
If you'd like to get the promise value you should do it inside the success callback, like this:
var final;
$http.get('someUrl').success(function(response) {
final = response;
});
No need for resData, will only cause a promise chain, something you don't require in this case.

Not able to return value even with callback function

I have read the following questions and corresponding insightful answers and understood how asynchronous call back functions work-
How do I return the response from an asynchronous call?
How to return value from an asynchronous callback function?
Returning value from asynchronous JavaScript method?
But still not able to successfully return the appropriate vaule. Following is the code -
function foo(callback){
request('some-url.json', function (error, response, body) {
//Check for error
if(error){
//error body
}
//Check for right status code
if(response.statusCode !== 200){
//response body
}
//All is good. Print the data
var data = JSON.parse(body);
callback(data.some-property);
});
}
module.exports = {
foo:foo(function(result){
console.log(result); //works
return result; //doesn't work
}),
};
I am able to get the expected result in the console log but still its not able to return the value.
Error: TypeError: Property 'foo' of object #<Object> is not a function
Problem:
1.Is the callback function execution correct?
2.What should I do to return the value successfully?
Edit: Finally after an extensive conversation with Paarth I have decided to resort to promise.js which will allow me to indirectly return the value I seek from my function. For further resources regarding promise.js -
https://gist.github.com/domenic/3889970
https://www.promisejs.org/
http://colintoh.com/blog/staying-sane-with-asynchronous-programming-promises-and-generators
Also worth mentioning : Bluebird & q
There's no real way to go from asynchronous code back to synchronous code. You can get close by using promises which treat delayed operations as data so you can return the promise object and set up actions that will happen on it later, but with callbacks you have to just keep creating callbacks.
You can find some basic information on promises here https://www.promisejs.org/ (though I'm not endorsing promise.js) and more here.
If you're working in ES5 Bluebird and Q are well known promise libraries. Promises are native functionality in ES6.
So ignoring the module syntax let's say you're trying to use that function.
function something() {
...
// result not bound, foo is not called
foo(function(result){
console.log(result); //result was passed into this callback and is bound
return result; //result is still bound but returning does nothing. No one is waiting for the return value.
});
// code below this point probably already executed before your console.log in the foo callback. No one is waiting for the return.
}
Responding directly to your questions:
Yes, you called foo correctly until you tried to return something. Returning isn't really a concept that applies to callback functions. You can only pass the data on to other callbacks.
You don't ever return the value.
Let's say I have foo, which takes in a callback. If I want to act on foo's result in another function, foo2, I have to call
function foo2 () {
foo(function(result) {
//act on result
}
}
Now let's say I want foo2 to return foo1's result to yet another function. Well, with callbacks, I can't. I can only ask foo2 to take in yet another callback and pass on the data.
function foo2 (callback) {
foo(function(result) {
callback(result);
}
}
That's because module.exports won't wait to the request (asynchronous) to finish. Simply export the function and call it somwhere when you want.
You can export the function :
//yourController.js
module.exports = foo;
Now require that function somewhere in other file and call it :
// another.js
var foo = require('yourController.js');
foo(function(result){
// your result is here
});
Or
require('yourController.js')(function(result){/* Do whatever with result */});

AngularJS promise not working

I have a promise that runs without a problem when it runs during application start, e.g.
myPromise
.success( function(data) { $scope.myvariable = data })
.error( function(msg, code) { console.log("msg: " + msg + "\nCode" + code) });
However if I try to run the promise dynamically, let's say when a button is clicked, (1) the promise executes successfully but none of my variables are updated.
running apply or digest only produces the following error: $digest already in progress
$scope.getContent = function() {
myPromise
.success( function(data) {
$scope.myVariable = data; //THIS WORKS
console.log(data); //THIS WORKS
})
}
//Running the below code afterwards still produces a null value
console.log($scope.myVariable);
This is what we called as async world.
When you are waiting for the callback of your promise the statement console.log($scope.myVariable); already executed but still you don't have any value in it.
In that case you can use $watch if you want to get it value outside.
$scope.$watch('myVariable',funciton(newVal){
console.log(newVal);
});
Little Detail:-
myPromise is invoked and waiting for the response in the meanwhile the statement console.log($scope.myVariable); after it executed which obviously doen't have any value for $scope.myVariable inside it (nobody gave it :-P). So when response came back it call the success or error method and initialize the value to your variable $scope.myVariable and print it.
Here your console.log($scope.myVariable); statement executes before success callback so here you need to do .then() chaining or apply watch on scope variable.
The reason your console.log, which comes after your promise logs null is because it is executing before your promise returns. Even though the function using the promise has run, the success part of the code has not fired yet. The code hits the promise, makes the calls, creates the promise object, and moves on. When the promise returns, it fills in the empty promise object with the returned data. This is happening after your
console.log($scope.myVariable);
A good way maybe to handle it is to store the returned value in a variable. Inside the success set the variable to the returned data, then use a function like
$scope.myVariable = undefined;
$scope.getContent = function() {
myPromise
.success( function(data) {
$scope.myVariable = data; //THIS WORKS
console.log(data); //THIS WORKS
})
}
function checker() {
if($scope.myVariable) {
console.log($scope.myVariable);
}
}
Then you can call that function as needed.
Depending on what you are doing and when your getContent function needs to run, you may want to use this with ui-router, and use resolve, which will run these functions before the page loads, thereby ensuring you have data to work with when the DOM loads.
AngularJS UI-Router: preload $http data before app loads
I think promise object makes call only once,when controller is initialized
you have to reinitialize controller,to get new updated values from server
A. Call sequence will be as follows when DOM ready:
1. $scope.getContent will get initialized.
2. then execution : console.log($scope.myVariable);
B. Async call:
1. If success then below statement will get executed.
$scope.myVariable = data; //THIS WORKS
Above point A and B are independent. Execution is asyc here.
Hope this will help you understand. Enjoy.
Maybe this can help :
// a service providing data with async call
app.service('myService', function(elasticQuery) {
this.getData = function (a,b,c) {
// don't forget the 2 return
return elasticQuery.search({
// make ajax call
}).then(function (response) {
return response
});
};
});
// in my controller
// scope.getData is lunch with ng-click in the view
$scope.getData = function(a,b,c){
myService.getData( a,b,c ).then(function (data) {
$scope.myVariable = data;
});
};

Does this JavaScript function need to return a Promise?

Let's say I have some JS that makes an AJAX call like this:
$.getJSON(myUrl, { targetState: state }, function (jsonData) {
}).success(function (jsonData) {
...
...
...
});
Now let's assume I want to wrap this code in a function and have it return some value, in the success block, so I can call it from various places in my app. Should the function I create return a Promise? I'm thinking it probably does, but I've never created a JS function that returned a Promise so I'm not entirely certain when I need to do this.
Should the function I create return a Promise
Yes. If you want to use promises, every function that does anything asynchronous should return a promise for its result. No exceptions, really.
wrap this code in a function and have it return some value in the success block
Good news: It's not complicated, as $.getJSON does already give you a promise to work with. Now all you need to do is to use the then method - you can pass a callback to do something with the result and get back a new promise for the return value of the callback. You'd just replace your success with then, and add some returns:
function target(state) {
var myUrl = …;
return $.getJSON(myUrl, { targetState: state })
// ^^^^^^
.then(function (jsonData) {
// ^^^^
/* Do something with jsonData */
return …;
// ^^^^^^
});
}
With promises, you do no more pass a callback to the $.getJSON function any more.
so I can call it from various places in my app
Now, you can call that target function, and get the result of the returned promise in another callback:
target({…}).then(function(result) {
…; return …;
});

Categories