Reputation: 2174
I'm using the twit library for nodejs which have async calls, and I made functions like this:
function getUserFromSearch(phrase) {
T.get('search/tweets', { q: phrase+' lang:pt', count: 1 }, function(err, data, response) {
data['statuses'].forEach(function(element) {
var result = "maybe";
say('getting user profile from search for '+phrase, result);
console.log(element);
return element['user']['screen_name'];
}, this);
})
}
Since T.get() is executed asynchonously, whenever I do
var username = getUserFromSearch('banana');
I get username=undefined
because it takes time to return things. The obvious solution would be to implement a callback like this:
function getUserFromSearch(phrase, callback) {
T.get('search/tweets', { q: phrase+' lang:pt', count: 1 }, function(err, data, response) {
data['statuses'].forEach(function(element) {
var result = "maybe";
say('getting user profile from search for '+phrase, result);
console.log(element);
callback(element['user']['screen_name']);
}, this);
})
}
But I don't think this is the best solution, because I need to create a callback function just for this. Isn't there a way to pass the username 'pointer' like this: getUserFromSearch('banana', username);
in such a way that the function alters the value of username? Is there even a better way?
Upvotes: 0
Views: 135
Reputation: 724
Since JavaScript doesn't have the notion of pointers,you can create an object before calling the function and pass the object as the second parameter to the function. Assign the result of the function to the object's property.
Your code would look like:
function getUserFromSearch(phrase,obj) {
T.get('search/tweets', { q: phrase+' lang:pt', count: 1 }, function(err, data, response) {
data['statuses'].forEach(function(element) {
var result = "maybe";
say('getting user profile from search for '+phrase, result);
console.log(element);
obj.username = element['user']['screen_name'];
}, this);
})
}
var obj = {username:null}
getUserFromSearch('banana',obj);
Upvotes: 1
Reputation: 1074305
Isn't there a way to pass the username 'pointer'
No, there isn't. JavaScript doesn't have references to variables.
You could pass in an object with a username
property and have it set that property, but that tightly couples getUserFromSearch
to a specific object and isn't composable.
Promises are a great way to handle this situation. They're composable and offer clear semantics around success and failure:
function getUserFromSearch(phrase) {
return new Promise(function(resolve, reject) {
T.get('search/tweets', { q: phrase + ' lang:pt', count: 1 }, function(err, data, response) {
if (err) {
reject(err);
} else {
data['statuses'].forEach(function(element) {
var result = "maybe";
say('getting user profile from search for ' + phrase, result);
resolve(element['user']['screen_name']);
}, this);
}
})
});
}
Usage:
getUserFromSearch(phrase).then(function(result) {
username = result;
});
Yes, there's still a callback, but it's a callback that's readily composed with others.
With ES2015 syntax:
function getUserFromSearch(phrase) {
return new Promise((resolve, reject) => {
T.get('search/tweets', { q: phrase + ' lang:pt', count: 1 }, function(err, data, response) {
if (err) {
reject(err);
} else {
data['statuses'].forEach(element => {
const result = "maybe";
say('getting user profile from search for ' + phrase, result);
resolve(element['user']['screen_name']);
});
}
})
});
}
Usage:
getUserFromSearch(phrase).then(result => {
username = result;
});
Upvotes: 1
Reputation: 38519
This is the way javascript works.
Since this is an async function, you'll need to do it as you said.
getUserFromSearch('banana', function(username){
//do something with username here
});
What you can do, is use something like async.js to reduce the nested callback hell...
Upvotes: 0