在javascript中从异步函数返回值的最佳方法

时间:2017-01-07 12:15:39

标签: javascript node.js asynchronous callback

我对使用异步调用的nodejs使用twit库,我做了这样的函数:

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

由于T.get()是异步执行的,每当我做

var username = getUserFromSearch('banana');

我得到username=undefined因为返回东西需要时间。显而易见的解决方案是实现这样的回调:

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

但我不认为这是最好的解决方案,因为我需要为此创建一个回调函数。是不是有办法传递用户名'指针'像这样:getUserFromSearch('banana', username);这个函数改变了用户名的值?还有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

  

没有办法传递用户名'指针'

不,没有。 JavaScript没有引用变量。

您可以传入一个包含username 属性的对象并让它设置该属性,但这会将getUserFromSearch与特定对象紧密联系起来并且不会可组合的。

承诺是处理这种情况的好方法。它们可以组合并提供关于成功和失败的明确语义:

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

用法:

getUserFromSearch(phrase).then(function(result) {
    username = result;
});

是的,还有一个回调,但这是一个很容易与他人合作的回调。

使用ES2015语法:

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']);
                });
            }
        })
    });
}

用法:

getUserFromSearch(phrase).then(result => {
    username = result;
});

答案 1 :(得分:1)

由于JavaScript没有指针的概念,因此可以在调用函数之前创建对象,并将对象作为第二个参数传递给函数。将函数的结果分配给对象的属性。

您的代码如下:

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

答案 2 :(得分:0)

这是javascript的工作方式 由于这是一个异步函数,你需要像你说的那样去做。

getUserFromSearch('banana', function(username){
   //do something with username here
});

你可以做的是使用类似async.js的东西来减少嵌套的回调地狱......