0

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?

0

3 Answers 3

1

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;
});
Sign up to request clarification or add additional context in comments.

3 Comments

Can I use ES2015 syntax in nodejs?
@Gatonito: Yes. Node v6.x has full support other than modules (and tail-call optimization unless you use a flag). v5.x and v4.x had partial support.
Then you can use it like this: var username = await getUserFromSearch(phrase); once node supports async/await.
1

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);

Comments

0

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...

3 Comments

What do you think of this idea: stackoverflow.com/questions/5292159/…
Instead of passing a callback I could pass a object that contains the 'username' property and make the function modify it.
would love it if people commented, not just fly-by downvoted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.