Assing variable from inner callback [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
In my honest opinion this question is not duplicated because I know how to fix it using a callback as explain in the linked question, this question is specific about a situation where I cannot modify the outfer function and this is not covered in the another question
I use a library that I cannot modify, the library do something like this:
var result = Foo()
Then it uses result for the work. I can not modify how result works, I can only modify Foo because I pass it as parameter to the library.
If foo has something like this
funcion Foo(){
return "Hello"
}
It works perfect. Result is Hello and it works.
The issue is that my Foo has an async call inside it. It calls a web server and then it should return the response of the server. So
funcion Foo(){
request.get('http://server.com', function(error, response, body){
var parsed = JSON.parse(body);
return parsed.Hello;
});
}
In this case when var result = Foo();, result does not contains the response of the server (because is async) and continue with an empty result.
So if I only can modify Foo what should I do?
Update: If you dont find it possible I would love to hear alternatives like what should I ask in PR for the library, or a way to force the request to be syncronous

This is how you can work with a synchronous request:
funcion Foo(){
var request = new XMLHttpRequest();
request.open("GET", "http://server.com", false);
request.send();
function handleResponse(response) {
console.log(response);
}
handleResponse(request.responseText);
}
If you can only modify Foo, then modify it to send the request synchronously.

What you're trying to do is impossible per se, once code is asynchronous, it can't be used as you would synchronous code. That's why callback hell is a thing.
You could try to analyze the module internals and monkey patch it, but that may not be possible depending on what exports the module exposes.

Related

Get content from .json and write to variable [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
What is the best way to just grab the content of a .json and store it to a var ?
I've seen some threads but i just can't manage on my code...
function retrieve_json() {
var content;
$.when(
$.getJSON("http://localhost/browsergame/data/test.json", function(data) {
content = data;
})
).then(function () {
console.log(content);
return content;
});
}
var json_content = retrieve_json();
console.log (json_content);
the console.log within the function displays the correct content of the json, the console.log at the very end of my code shows 'undefined'. I guess the async is the main issue here. I have tried doing it with $.ajax but couldn't manage either.
So, what is the best way to just grab the content of a .json file and store it to a var ?
The problem is that retrieve_json wont stop and wait until the json arrives from the server. The execution continues with whatever is after the statement starting with your $.when. In this case it's the end of the function. Since there is no return statement here, the function returns with the value 'undefined', what you store in json_content.
If you want to stop execution until the answer returns you have to wrap the next steps into a function and for example call it in the 'then' method of your example or just pass it to the getJSON where you store it in the content variable now.
And make sure you read up on how promises work.
Once code is async, it can't be made synchronous. You can only reliably use the content of your JSON in functions that you pass to promises or as callbacks, otherwise you have no guarantee that your JSON has been fetched when your code gets executed.
If you find even the promises syntax horrible you might be interested in async/await, a proposed syntax for ES7 that can be transpiled to ES5 right now with Babel.
Here's a good article which demonstrates the different approaches to asynchronous programming in JavaScript: The long road to Async/Await in JavaScript.

javascript object/variable issue [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have below code in angular service
this.get = function(url,qParams)
{
var webresponse = new Object();
$http.get(url+qParams)
.success(function(result){
webresponse.data = result;
webresponse.state = 1;
})
.error(function(result){
webresponse.data = result;
webresponse.state = 0;
});
console.log('webresponse :' + webresponse.data);
return webresponse;
}
In console log shows webresponse.data as undefined. Please help me to understand why. Is it scope issue?
just to let you know result is JSON array and in console log it shows JSON array as expected with all elements in it.
Your $http.get() is an async call and your console.log is in synchronous fashion, so console.log initiated first then your $http.
Method calls in $http are asynchronous: The result will not be necessarily available after the function .get() returns. Please check again the docs for $http.
Data in webresponse will not be available (i.e. your variable is not set yet to anything other than the plain object) but only when the $http.get request fetches the data from the server. Such moments are the .success trigger, the .error trigger, and also a trigger you did not use (and perhaps don't need) called .finally (works regardless whether .success and .error have been triggered).
You cannot access the webresponse outside those callbacks since they are the only guaranteed moments where such values will be available. Even more! You cannot RETURN such value from the function. Since the behavior is asynchronous you will have to return something in the same asynchronous way. Please check the $q service to learn how to do it. It is a long topic and you lack the basics on this topic so I will give you some guidelines:
$http is an asynchronous service. Their calls (e.g. .get() return something called a promise. Your function should return a promise (either the same or other).
The actual result itself (i.e. the result you want) will not be available as you intend: The function's invoker must attend the promise you return, specify a callback for it, and attend it in the callback.
More information: You need a deeper knowledge of $http and $q services. They are pretty well documented in the official docs.
you function is an synchronous call.
this.get = function(url,qParams)
{
var webresponse = new Object();
$http.get(url+qParams)
.success(function(result){
webresponse.data = result;
webresponse.state = 1;
console.log('webresponse :' + webresponse.data);
//triger any function #here when its success
})
.error(function(result){
webresponse.data = result;
webresponse.state = 0;
console.log('webresponse :' + webresponse.data);
//triger any function #here when its fail
});
}
Your this.get() function can't return result immediately.
As you know, the $http module use ajax, (AJAX: Asynchronous Javascript and Xml )
so you have to wait for the asynchronous response in your success or error callback function.
If you want to return the response, please consider promise pattern.

MarkLogic NodeJS JavaScript function return [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
Like a person asked here (but his solutions as to call a nother function) https://stackoverflow.com/a/10796326/315200 ...I would like to know if its possible to have a function which doesn't call a second function on response of an async request, but simply return when the async request responses.
Something like this maybe:
function callToFacebook() {
var fbResponse;
FB.api('/me', function (response) {
fbResponse = response;
});
return fbResponse; //Will return undefined because CallToFacebook is async
}
Isn't that possible some way, without calling another function??
What I'm trying to achieve is to have one function I can call with some parameters, which will return the response object from a async webservice, like FB.
In short, no. You cannot have an asynchronous function return a meaningful value synchronously, because that value does not exist at that time (as it is built asynchronously in the background).
You can, however, return a Promise object, representing the "potential return value" of the asynchronous operation, and bind a function to that object using done() or similar. That way, your function gets return semantics (instead of having to chain the control flow into a callback), and remains asynchronous.
No, it's not possible.
You can't return value that is returned from async operation.
Think about it, you tell 10 people to have one mile running contest, they start now, will finish in one minute +-, but you want to know the answer now, it's not possible unless you're cheating...

In NodeJs how can I wait until my http get is finished? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
EDIT: I want to explain the problem more clearly, my purpose is to make http response before "webot.waitRule()" returns. So should http request call back to webot.waitRule or the other way around?
below is my code which implements a module in a program, and my problem is
the function returns before the http request get its response. I know http requests in node
js is async, so there is any solution for it? I am pretty new in javascript and nodejs. Thanks.
webot.waitRule('wait_class', function(info) {
var courseName='lol';
var options = {
host: 'api.uwaterloo.ca',
path: '/v2/courses/CS/486/examschedule.json'
};
callback = function(response) {
var str = '';
//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});
response.on('end',function(){
// console.log(str);
// return "kkk";
var data = JSON.parse(str);
console.log(data['data']['course']);
courseName = courseName+data['data']['course'];
console.log("finished");
// return "lolllll";
// return "nide ke shi "+ courseName;
});
}
var req = http.request(options, callback);
req.end();
console.log("i am finshed");
return courseName;
});
Since node is primarily asynchronous and uses callbacks (as opposed to promises), you'd likely want to define a function that will be called that takes a parameter which is the output of your asynchronous call.
For example (in your case): you get courseName in the callback for response.on('end', .... You could define a function such as:
function processCourseName(name) {
console.log('do something with', name);
}
And then after console.log('finished');, just add a call to that method
...
courseName = ...
console.log("finished");
processCourseName(courseName); //whenever the request is finished, then process the course name in a separate function
More explanation: Your return courseName statement are exiting from the function before the http.request call is finished, and therefore before courseName is even assigned to a proper value.
More edit: I took a look at the webot module and it looks like its written in a way that doesn't support async code? Usually libraries pass a callback function you can call when your async processing is done, like function(info, callback) {}, but webot does not appear to. Your best bet might be to assign courseName to the info object (info.courseName) you are given and notify your program to use courseName elsewhere.
Notes:
You should use somthing like mikeal/request to make requests outwards, as it's written specifically to do so.

JQuery $.post in a function. Wait for callback to define the return. [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
How would I, using $.post() in a function, force the return on the post callback?
Example:
function myFunction(){
$.post(postURL,mydata,function(data){
return data;
});
}
I have tried playing around with it using .done() and .queue() however neither has worked for me.
I understand there is a fundamental flaw in my example; with that said, how can I achieve my desired functionality?
This is impossible. $.Ajax calls will always return immediately. You need to deal with the return when it is called through a callback (possibly several seconds later). Javascript never blocks for a given call. It may help to think of your code like this:
//This entirely unrelated function will get called when the Ajax request completes
var whenItsDone = function(data) {
console.log("Got data " + data); //use the data to manipulate the page or other variables
return data; //the return here won't be utilized
}
function myFunction(){
$.post(postURL, mydata, whenItsDone);
}
If you're interested more on the benefits (and drawbacks) of Javascript's no-blocking, only callbacks: this Node.js presentation discusses its merits in excruciating detail.
function myFunction(){
var deferred = new $.Deferred();
var request = $.ajax({
url: postURL,
data: mydata
});
// These can simply be chained to the previous line: $.ajax().done().fail()
request.done(function(data){ deferred.resolve(data) });
request.fail(function(){ deferred.reject.apply(deferred, arguments) });
// Return a Promise which we'll resolve after we get the async AJAX response.
return deferred.promise();
}

Categories