Accessing Return Variable Declared in 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.
So I am going to preface this by saying that my understanding of callback functions is limited so there is a chance I am making a beginner mistake with either callbacks or RequireJS.
Essentially, what I am looking for is the ability to access the values of the method from an API and create a variable by looping through what is contained inside the callback function. I then want to take that variable and return its value in the return portion of my RequireJS define statement. Below is a simplified example of what I am trying to do.
//call an api library then loop through to get all values for your object
define(['apiLibrary'], function (api) {
//create var that contains api method of current object
var apiMethod = api.someMethod();
//declare value var to be used inside callback
var value ='';
//call otherMethod, specifying an arguement and use callback to access contents of method
apiMethod.otherMethod('arg',function (reply) {
//loop through each value inside callback
$.each(reply.item, function (key, value) {
//add values to variable for each instance of method
value += 'the key is '+key+' and the value is'+value;
});
});
//return some values as well as the value set above for the overall define method
return {
valueFromElsewhere: 'hardcoded for example',
valueFromLibrary: value //value is '' since it is set insde a callback function
}
});
I appreciate any help I get in advance! Thanks!
EDIT:
The information on promises is extremely helpful and definitely helps me wrap my head around asynchronous functions in general but I need to return my variable data in a RequireJS return statement. There is a downstream program, that I have no control over, expecting data to be returned in a specific format that is provided by the return value of my define function.

You'll need to access the value asynchronously. A great way of handling that is a Promise:
var getValue = new Promise(function(resolve, reject) {
apiMethod.otherMethod('arg',function (reply) {
$.each(reply.item, function (key, value) {
value += 'the key is '+key+' and the value is'+value;
});
resolve(value);
});
});
return {
valueFromElsewhere: 'hardcoded for example',
getValueFromLibrary: getValue
};
You can then access it using the .then api:
foo.getValueFromLibrary.then(function(value) {
console.log('Value:', value);
});

Related

Why is firebase returning a pomise? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I have checked and read the other posts about making an asynchronous calls which tells me to handle the promise, this post is different because I am expecting my call to have already handled that
I am trying to get the current score of a specified user. However, instead of returning the score I am getting (in the console):
the current score in my firebase database is 3. Here is the function I have:
function getCurrentScore() {
var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).child('score').once('value').then(function(snapshot) {
console.log(snapshot.val());
});
}
what I want to do is assign the value to a variable that I can use. For example
var score = getCurrentScore();
How can I get this value and assign it to a variable in firebase?
Edit for clarification:
So, I know that this is making an asynchronous call, however I thought that .then only works once that call has completed. Is this not the case? Does firebase handle this differently?
Here is what I thought from https://howtofirebase.com/promises-for-firebase-bbb9d0d595ed:
Returning a value out of a .then() callback and returning Promise.resolve() has the same result.
I am a noob junior so please do not crucify me. Extra points for detailed explanations that help me learn and increase my understanding..
What i do usually in this type of cases is that i return the promise from the function and handle the promise directly where i need the returned data. e.g i would change it to
function getCurrentScore() {
var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).child('score').once('value');
}
And than wherever i need the data i would do:
getCurrentScore().then(function(snapshot){
var score = snapshot.val();
})
Or you can also work something out with async/await to(still a promise). The main point is you leave the responsibility of handling promise to the function which needs the data

NodeJS Synchronous Trouble [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
Using NodeJS, I'm trying to get info from the database on a list of IDs and populate an array of objects. I need this to process synchronously. I'm having trouble figuring out how to do this so the next function call will wait for the previous one to finish before being called. Then all of the 'each' iterations to finish for the return to be called.
Example:
getInfo();
function getInfo(){
var return_arr = Array();
var ids = getListOfIDs();
// loop through each id getting more info from db
$.each( ids, function( i, v ){
return_arr.push(getFullInfo( id ));
});
return return_arr;
}
function getListOfIDs(){
// database call to get IDs
// returns array
}
function getFullInfo(){
// database call to get full info
// returns object
}
This is a simplified example, so assume that a single query to get all info will not work as there are multiple joins going on and post processing that needs to take place in js. Also, assume I'm doing proper error handling, which I omitted in my example.
Your database queries are asynchronous so you need to either use callbacks or promises to perform your work once the database returns with results.
function getListOfIDs(callback) {
// database call to get IDs
db.query('...', function(data) {
// call the callback and pass it the array
callback(data);
});
}
function getInfo() {
// pass an anonymous function as a callback
getListofIDs(function(data) {
// we now have access to the data passed into the callback
console.log(data);
});
}
Your current code example is synchronous, although I don't know how your db code works. The each loop is synchronous it just iterates over your ids and calls the getFullInfo function.
I'm not sure why you want synchronous code though as it doesn't utilise Nodes event loop architecture.
What I would do is use a good Promises framework such as Bluebird (http://bluebirdjs.com/docs/api/promise.each.html) with Promise.each ensuring each iteration occurs serially. Or you could also use a Callback library such as async (http://caolan.github.io/async/) with async.eachSeries. Either of these will ensure that you (a) get the benefit of asynchronous and (b) iterate in a serial fashion.
Promise way to do it:
function getListOfIDs() {
return new Promise((resolve, reject) => {
// database call
if (err)
{
reject(your_db_err);
return;
}
resolve(your_db_result);
});
}
function getInfo() {
getListOfIDs().then((result) => {
//do whatever you want with result
})
.catch((err) => {
//handle your err
});
}

Access to a variable, which is output from an async function [duplicate]

This question already has answers here:
Saving data from the d3.js ajaxrequest in a variable to create axis with data
(2 answers)
Closed 7 years ago.
I have a problem with this snippet:
d3.csv("data/airports.csv", function(err, a) {
var count=0;
a.forEach(function(i){
if(i.iata_faa == ""){}
else {
count++;
addpoint(i.lon, i.lat,i);
}
});
airports=a;
myDataIsReady();
console.log(count);
});
function myDataIsReady(){
console.log(airports);
return airports;
}
console.log(airports);
Notice that airports is a global variable here.
I need to handle the variable airports for another function, but the value is null, I think that is null because the csv file has not yet been processed completely, right?
How I resolve it?
Generally for async functions, you push a callback (a function reference) into the async method, so that it processes the data when the ajax call completes. You don't return data from that type function, you inject data into it.

Scope in JavaScript / jQuery [duplicate]

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.

Return object list Jquery Ajax [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I'm calling a C# api through Jquery AJAX. I am able to loop through all of the data and print each in the console; however, I am not able return the data to a variable (var x) so that it contains all objects returned from the api call.
This is my code thus far:
var uri = 'api/products';
function test(){
// Send an AJAX request
$.getJSON(uri)
.done(function (data) {
// On success, 'data' contains a list of products.
var info = {};
$.each(data, function (key, item) {
// Add a list item for the product.
console.log(item);
info.append(item);
});
return info;
});
}
var x = test();
I have tried to just simply skipping the $.each() and returning data, with no luck.
Should I be using a method other than append? Or is there a way to just simply return data?
Thanks.
.done() is a promise (http://api.jquery.com/promise/), which takes a callback function. The callback function is void; nothing consumes its return...and the return in your code is the return for the (anonymous) callback function, not for test(), which is why you're seeing no value come out.
This is an asynchronous pattern. That means test() is going to return immediately, not waiting for the AJAX call to complete, and there's no value yet to put into x! The AJAX response will arrive later, at some unknown time. The purpose of the callback function is to allow you to (at that time!) do whatever it is you intend to do with the value you receive. You haven't shown us what that is in this example, but you're going to need to restructure it to happen after the promise is fulfilled.

Categories

Resources