This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
as mentioned above i have an issue getting the data out of the scope, which i set in the scope before in an asynchronous callback function.
Here is some of my Code:
var TransactionCtrl = require("controller/transactions.controller");
var onSuccess = function(_response) {
this.showData = _response;
};
var TransactionsFunction = function() {
//preparing asynchronous call
var transactionCtrlInstance = new TransactionCtrl(onSuccess.bind(this));
//firing asynchronous call
transactionCtrlInstance.getTransactions();
};
TransactionsFunction.prototype.run = function() {
//show this.showData
console.warn(this);
console.warn(this.showData);
};
module.exports = TransactionsFunction;
Important to mention is, that i call the "run" function definitely after the asynchronous call returned, so the data should be applied in the scope.
Does somebody have an explanation or a workaround for this?
Does the scope behave different in a callback function even if i bind the scope on it?
Calling the run method on new TransactionsFunction() will not guarantee that the async call had been completed.
The new TransactionsFunction() would fire the asysnc call and then exit.
If you call run() the async call may still have not been returned.
The only place you can ensure that the data has been returned is the onSuccess () method.
Your can check out incorporating such behavior using Promises.
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
var preGameRequest = new XMLHttpRequest();
var preGameData;
preGameRequest.open("GET", "/matches/live.json");
preGameRequest.onload = function() {
preGameData = JSON.parse(preGameRequest.responseText);
}
preGameRequest.send();
console.log(preGameData); // main problem is here
Here is my code. I defined preGameData as global and tried to save /matches/live.json file's data into preGameData. And when I try to console.log(preGameData) from outside of the scope (like in the code section) I get 'undefined' as a return. And if I try to console.log(preGameData) from inside of the scope it works. I don't really know what's going on.
That code should work:
preGameRequest.onload = function() {
preGameData = JSON.parse(preGameRequest.responseText);
console.log(preGameData);
}
The reason: is that preGameRequest.send() function operates asynchronous.
When the browser tries to execute console.log() (in your example), the http response is not recieved yet, and the variable is really undefined.
But if you place console.log() inside of the handler (as in my example), it would be executed at moment, when the response is already recieved (straight in the onload() handler). And that's why the variable preGameData would be defined already.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am relative new to node.js and I ran into a problem where a function is returning undefined. I use console.log to make sure that it returns the proper value and it does. But in the script that makes the call to the function shows as undefined. I think this may be an issue with async programming? I am trying to learn more on how promises work in node.js. What am I doing wrong?
The reason why I believe that it is a problem with async is because console.log is printing to the console undefined before the console.log in getCurrentFrameName();. var name is being assigned undefined.
frameHandler.switchToFrame('top_page');
var name = frameHandler.getCurrentFrameName();
console.log(name);
The console.log in this method prints to the console after the console.log in the code above. The value printed to the console of name is top_page.
this.getCurrentFrameName = function()
{
driver.executeScript('return self.name').then(function(name) {
console.log(name);
return name;
});
};
You can do this:
this.getCurrentFrameName = function(callback) {
driver.executeScript('return self.name').then(function(name) {
return callback(name);
});
};
and then call it like this:
frameHandler.getCurrentFrameName(function(name) {
console.log(name);
});
this will fix your problem, but yes, is a sync problem.
Yes, this is an issue with asynchronous programming. You cannot return a value from an asynchronous callback.
This is because the callback waits for the asynchronous script to execute, and so, node immediately passes control to the next line after the callback.
In your case, console.log(name); gets called before the callback is executed. Hence, the undefined.
The simplest solution to the current situation is to perform the necessary computations within the callback itself.
However, in more complicated situations (such as, callback within callback) you can easily end up with what is known as callback hell.
There are several ways to deal with callback hell: one of them is something called Promise.
What a Promise does essentially, is that it brings a sense of linearity to the code, thus making it easier to understand and maintain.
In your case, you can do this:
this.getCurrentFrameName = function() {
var myPromise = driver.executeScript('return self.name');
myPromise.then(function(name) {
// Do all computation with `name` here
});
};
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I've clearly been writing too much CoffeeScript, as I am now realizing I do not have even a basic understanding of scope in pure JS.
After playing for a while, I cannot figure out the problem with the following--
$(document).ready(function() {
var myUrl = "http://notimportant.com/"
var photos = getPhotos(myUrl);
console.log(photos); //undefined
});
function getPhotos(url) {
var a;
$.get(url, function(data) {
a = data["photoset"]["photo"];
console.log(a); //my object
});
return a;
}
If I put a console.log(a) statement on the line right below 'var a = data["photoset"]["photo"];' it shows that it properly makes the GET request I'm looking for. But I'm finding it impossible to pass that object back to my main block of code, where I want to manipulate it.
Thanks in advance.
The reason photos is undefined is not because of scopes. Its because $.get is executed asynchronously. $.get() returns jqXHR object instead of an HTTP response.
onSuccess callback should be passed to getPhotos() in order to make it work correctly. Alternatively when().then() construct could be used.
$(document).ready(function() {
var myUrl = "http://example.com/";
getPhotos(myUrl, renderCatPhotos);
});
function getPhotos(url, onSuccess) {
$.get(url, onSuccess);
}
function renderCatPhotos(data) {
var a = data.photoset.photo;
console.log(a); // a is always available
}
note: you might not even need getPhotos function. You can simply $.get(url, onSuccess); in $(document).ready() instead.
Its not a matter of scope, its a matter of that you are returning an undefined variable before the $.get defines it. Consider making photos a global, then setting it in the $.get success function instead of setting it to 'a'. Inside the success function, you can then issue calls to other functions that would control displaying/processing the photos.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
I'm trying to get a variable (lib) out of a multiple nested functions.
var nme='name',lib;
$('script').each(function(){
var src=$(this).attr('src');
if(typeof(src)==='undefined'){src='';}
if(src.indexOf(nme)!==-1){
$.get($(this).attr('src').match(/\w([^ ]+)spbin/)[0]+'/conf/ptmedia.plist',
function(c){
$(c).find('key').each(function(){
if($(this).html()==='MediaLib'){lib=$(this).next().html();}
});
}
);
}
});
if(lib==='some lib'){DO STUFF}
Your problem isn't with scoping, the problem is that you have an AJAX call which is asynchronous.
You should put the change of HTML in .null inside the callback function instead:
$.get($(this).attr('src').match(/\w([^ ]+)spbin/)[0]+'/conf/ptmedia.plist',
function(c){
$(c).find('key').each(function(){
if($(this).html()==='MediaLib'){lib=$(this).next().html();}
$('.null').html(lib);
});
}
});
In JavaScript often IO is asynchronous. This means that when you make an AJAX call it does not happen immidiately but rather waits for the value to return from the HTTP request and then calls a callback. In your case that function(c) is the callback, it gets executed when the value of the AJAX call arrived.
So in fact you were updating the HTML content of .null to undefined, since it got the value of lib before it was updated.
I solved this problem as follows:
var nme='name';
$('script').each(function(){
var src=$(this).attr('src');
if(typeof(src)==='undefined'){src='';}
if(src.indexOf(nme)!==-1){media=$(this).attr('src').match(/\w([^ ]+)spbin/)[0];}
});
function ffn(){
$($.ajax({url:media+'/conf/ptmedia.plist',async:false}).responseText).find('key').each(function(){
if($(this).html()==='string'){value=$(this).next().html();}
});
return value;
}
if(ffn()==='some lib'){DO STUFF}
Thank you all for your participation and good ideas!
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...