Issue accessing variable outside of function scope [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I'm pulling data from an XML feed. That is all working correctly but I need productIDs available outside the function.
// Get feed data
$.get('example-feed.xml', function (data) {
var $xml = $(data);
// Collect array of product IDs
var productIDs = [];
// extract ids from xml
$xml.find("item").each(function() {
var $this = $(this)
item = {
id: $this.find("id").text()
}
// get the id
var itemID = item.id;
// push ids to array
productIDs.push(itemID);
});
console.log(productIDs); // Works as expected
});
console.log(productIDs); // Undefined, also as expected
How can I adjust my function to work like that?
example = function(){
var productIDs = "my content ids"
return {'productIDs': productIDs}
}
var retrive = example();
console.log(retrive.productIDs);

There are multiple ways you can do this, but the best thing here is to use promises, because JQuery's get is usually asynchronous function and you have to wait for it's completion to get product ids
You may do it like this
function fetchThings () {
return new Promise(function (yes, no) {
$.get('example-feed.xml', function (data) {
// some code here
console.log(productIDs); // Works as expected
yes(productIDs);
});
});
}
fetchThings().then(function (productIDs) {
// do stuff with prodcut ids here
});
The other way to do it would be making your $.get call synchronous, so replace it by
var productIDs;
$.ajax({url: 'example-feed.xml', type: "GET", async: false, success: function (data) {
// process productIDs here
}});
// use productIDs here
Update:
Here is a snippet of async ajax, click run to check
var postIDs;
$.ajax({
url: 'http://jsonplaceholder.typicode.com/posts',
method: 'GET',
async: false,
success: function(posts) {
postIDs = posts.map(function (p) { return p.id; });
}
});
document.write(JSON.stringify(postIDs));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

How to use callbacks in other functions in JavaScript? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am stuck with how to use the variable inside a callback function from another function that is outside of callback...
Simple explanation of problem:
There is function that gets json from web. It takes some arguments already. On success, callback manipulates the data slightly. Now, another function responsible for updating the chart is meant to get the manipulated data from callback and do its own thing...
My code:
var mainData;
function getMainData (city, callback) {
this.city = city;
var url = "http://api.openweathermap.org/data/2.5/weather?q=appid=7ce3e1102e1902e0f878c2a640e95aed&london";
$.ajax ({
method: "GET",
type: "json",
cache: "false",
url: url,
success: callback
})
};
function callback (data) {
mainData = data;
var dArray = data.list.map(a=>a.dt)
var tempMinArray = data.list.map(a=>a.main.temp_min)
var tempMaxArray = data.list.map(a=>a.main.temp_max)
}
function changeChart (chartName, howToPassTempMinArrayHere?) { // <--- this is where I have no idea how to pass callbacks variables
chartName = chart.name.(....);
someDataFromMainData = chart.data.(....);
};
// on click of button (...) :
(
getMainData(callback); // why no action?? nothing??
changeChart (myChart, someDataFromMainData)
);
Just put the callback in the function like this:
var mainData;
function getMainData (city, callback) {
this.city = city;
var url = "http://api.openweathermap.org/data/2.5/weather?q=appid=7ce3e1102e1902e0f878c2a640e95aed&london";
$.ajax ({
method: "GET",
type: "json",
cache: "false",
url: url,
success: callback
})
};
function callback (data) {
mainData = data;
var dArray = data.list.map(a=>a.dt)
var tempMinArray = data.list.map(a=>a.main.temp_min)
var tempMaxArray = data.list.map(a=>a.main.temp_max)
// Put your code here
changeChart (myChart, someDataFromMainData)
}
function changeChart (chartName, howToPassTempMinArrayHere?) { // <--- this is where I have no idea how to pass callbacks variables
chartName = chart.name.(....);
someDataFromMainData = chart.data.(....);
};
// on click of button (...) :
(
getMainData(callback); // why no action?? nothing??
);

How to return data to variable after ajax call success [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 a PHP file returning data in required array format to my FlotChart, it's working.
Now I'm trying to get this result in my script using ajax, however I cannot see result on global variable, as described below:
myJS.js
var EcomDashboard = function() {
return {
init: function() {
var dataEarnings = NULL;
$.ajax({
url:"operation.php",
dataType: "text",
success:function(data) {
alert(data); //show my array [ [1, 20],[2,30],[3,14] ]
dataEarnings = data;
}
});
alert(dataEarnings); //showing "NULL" but I need [ [1, 20],[2,30],[3,14] ]
...
What is the correct way to assign to my variable date Earnings the array [[1, 20], [2.30], [3.14]]?
Javascript is an async language, it means it won't wait the http request to finish to execute the next line. you will have to assign the variable inside the success block.
the alert shows null is becauseit got executed before the $.ajax http request line finishes.
may be you can do this using a callback:
dataAccess.js
var ecomDashboard = function() {
init: function(callback) {
var dataEarnings = NULL;
$.ajax({
url:"operation.php",
dataType: "text",
success:function(data) {
callback(data);
}
});
}
}
controller.js
ecomDashboard.init(function(data){
// data contains the array result
// do your stuff
})
event better:
since jquery 1.5 there is incorporated promise interface, and .success is going to be deprecated. edited: thanks to Kevin B
so with promise:
dataAccess.js
var ecomDashboard = function() {
init: function(callback) {
var dataEarnings = NULL;
return $.ajax({
url:"operation.php",
dataType: "text"
});
}
}
controller.js
ecomDashboard.init().done(function(data){
//do your stuff
alert(data);
}).fail(function(error){
//do stuff when error
});
$.ajax({
url:"operation.php",
dataType: "text",
success:function(data) {
doSomthingOnComplete(data);
}
});
function doSomthingOnComplete(data)
{
// do here your work
}
This is occurring because that alert(dataEarnings) is executing before your ajax request resolves. The first letter in the AJAX acronym is Asynchronous. So, ultimately your data is being set properly you are just trying to access it before the asynchronous call completes.

JavaScript module that uses AJAX to set and return variables

I'm trying to write a module that makes two AJAX calls and sets variables to the results of those calls. I'd like to be able to access the results of those calls like myModule.firstCall and get the result of the AJAX call and not the promise.
var ajaxModule = (function () {
var subFolderData = {},
rootData = {};
var subFolderFile = function () {
return $.ajax({
url: 'Content/testData.json',
dataType: 'json'
});
}
var rootFile = function () {
return $.ajax({
url: 'testDataRoot.json',
dataType: 'json'
});
}
//only returning promise here, how to return $.when the call is done?
return {
rootFile: rootFile().done(function (data) {
subFolderData = data;
}),
subFolderFile: subFolderFile().done(function (data) {
rootData = data;
})
}
})();
//this prints out the dat as expected, but can I store the results in a variable
//to be accessed like ajaxModule.rootFile?
console.log(ajaxModule.rootFile.done(function (data) {
console.log(data);
}));
No, you cannot return the result from an asynchronous call.
Assigning them to a global (or higher-scope) variable, such as subFolderData or rootData in your example, is possible, but does not make sense because you do not know when the value will be available.
Storing the promises for the values, like your ajaxModule.subFolderFile and ajaxModule. rootFile, and always incorporating them when needing to access the data, is the way to go.

javascript variable is not showing correct value [duplicate]

This question already has answers here:
How to add callback to AJAX variable assignment
(4 answers)
Closed 8 years ago.
i have this ajax call function.
function saveData(ip)
{
$JQ.ajax({
type: "POST",
url: "all_actions.php",
data:
{
page_url:document.URL,
ip_address:ip
},
success: function(responce)
{
if(responce)
{
var newtoken;
newtoken=responce;
return newtoken;
}
}
});
}
Then i have another function
function getToken()
{
var ip=myip
var mytoken;
mytoken=saveData(ip);
alert(mytoken);
}
My token giving undefined in alert.Although if i alert newtoken variable in savedata response it gives correct value in alert box.why if i return that avlue it does not assigned to mytoken.
is it something time delay issue.??
Need your help...
You cannot return from an asynchronous call.
You have to consume the return data inside the success function. Whatever you are going to do with token, write that code inside the success handler.
success: function(responce)
{
if(responce)
{
var newtoken;
newtoken=responce;
// Global variable
sourceid = newtoken;
return newtoken; // This won't work
}
}
Also
function getToken()
{
var ip=myip
var mytoken;
mytoken=saveData(ip); // This won't return any data
alert(mytoken); // This won't give you anything useful
}
Hi friends This is solution that for i was looking.
function saveData(ip)
{
return $JQ.ajax({
type: "POST",
url: "all_actions.php",
data:
{
page_url:document.URL,
ip_address:ip
},
async: false,
}).responseText;
}
function getToken()
{
var ip=myip
var mytoken;
mytoken=saveData(ip);
return mytoken;
}
The first 'A' in AJAX is 'Asynchronous'. Your alert is running before the AJAX request has had a chance to complete. You need to handle whatever you wish to do with the response inside of the success: function() or .done() functions of jQuery:
success: function(responce)
{
if(responce)
{
var newtoken = responce;
// Work here with newtoken...
}
}

Issue with code inner variable

I have a code like the one stated below, please how do I get the value for (getData), using a code like:
var instanceArray = myGraph.getInstances(component)
I was thinking myGraph.getInstances(component).getData will do it, but it failed
this.getInstances = function(component) {
var getData = {};
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: true,
success: function(data) {
getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
}
});
};`
You can't, the get is asynchronous. getInstances returns before the GET completes, so it's impossible for getInstances to return the data. (See further note below.)
You have (at least) three options:
Use a callback
Return a blank object that will get populated later, and have the code that needs it poll it periodically
Use a synchronous get (not a good idea)
1. Use a callback
What you can do instead is accept a callback, and then call it when the data arrives:
this.getInstances = function(component, callback) {
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: true,
success: function(data) {
var getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
callback(getData);
}
});
};
And call it like this:
myGraph.getInstances(component, function(data) {
// Use the data here
});
2. Return a blank object that will get populated later
Alternately, you can return an object which will be blank to start with, but which you'll add the data to as a property later. This may be closest to what you were looking for, from your comments below. Basically, there's no way to access a function's local variables from outside the function, but you can return an object and then add a property to it later.
this.getInstances = function(component) {
var obj = {};
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: false, // <==== Note the change
success: function(data) {
var getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
// Make the data available on the object
obj.getData = getData;
}
});
return obj; // Will be empty when we return it
};
And call it like this:
var obj = myGraph.getInstances(component);
// ...later...
if (obj.getData) {
// We have the data, use it
}
else {
// We still don't have the data
}
3. Use a synchronous get
I do not recommend this, but you could make the call synchronous. Note that synchronous ajax requests will go away in a future version of jQuery. But just for completeness:
this.getInstances = function(component) {
var getData;
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: false, // <==== Note the change
success: function(data) {
var getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
}
});
return getData;
};
And call it like this:
var getData = myGraph.getInstances(component);
But again, I don't advocate that. Synchronous ajax calls lock up the UI of the browser, leading to a bad user experience.

Categories

Resources