Javascript异步函数:回调不起作用

时间:2017-10-01 15:09:53

标签: javascript ajax api http

我试图从Javascript中的异步函数返回结果。

我已经看到了这个问题:How do I return the response from an asynchronous call?,我正在尝试实现回调解决方案,但是出了点问题。

这是我的代码:

function getLocation(callback){
    var lat;
    var long;
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position)
                {
                    lat = position.coords.latitude;
                    long = position.coords.longitude;
                }, function()
                {
                    console.log('Please enable geolocation in your browser.');
                });
    } else {
        alert('It seems like geolocation is not enabled in your browser.');
    }
var res = {
        "lat": lat,
        "long": long
};
callback(res);
}

function getEventNearYou(){
    var list = [];
    getLocation(function(obj){
        var lat = obj.lat;
        var long = obj.long;
        $.ajax({
                url : 'http://www.skiddle.com/api/v1/events/search/?api_key=myapikey' + '&latitude=' + lat + '&longitude=' + long + '&radius=800&eventcode=LIVE&order=distance&description=1',
                type : "GET",
                async : false,
                success : function(response) {
                        $(response).find("results").each(function() {
                        var el = $(this);
                        var obj = {
                                    "eventname" : el.find("eventname").text(),
                                    "imageurl" : el.find("imageurl").text(),
                                  }
                        list.push(obj);
                        });
                        } 
                });
        return list;
    });
}

基本上,我想找到我当前的位置,并向www.skiddle.com创建一个HTTP get请求,以检索该位置附近的事件。

这就是我调用函数的方式:

var x = getEventNearYou();

但我似乎犯了一个错误,因为我收到了错误的请求错误(latlong未定义)。

2 个答案:

答案 0 :(得分:2)

您以一种破坏其有用性的方式使用回调。您仍然以同步方式编写代码。您应该继续参考:{{3}}

与此同时,我会重新构建您的代码,以显示它是如何完成的。

  1. 根据经验,如果函数中的任何代码使用回调,那么外部函数也需要接受回调作为参数。

  2. 如果在回调函数中为变量赋值,则不会在回调函数之外定义它(因为异步代码总是在同步代码之后运行)。 / p>

  3. 请勿使用async: false

  4. function getLocation(callback){
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function (position) {
                var lat = position.coords.latitude;
                var long = position.coords.longitude;
                var res = { "lat": lat, "long": long }; 
                callback(res);
            }, function() {
                console.log('Please enable geolocation in your browser.');
            });
        } else {
            alert('It seems like geolocation is not enabled in your browser.');
        }
    }
    
    function getEventNearYou(callback) {
        getLocation(function(pos){
            var lat = pos.lat;
            var long = pos.long;
            $.ajax({
                url: 'http://www.skiddle.com/api/v1/events/search/?api_key=myapikey' + '&latitude=' + lat + '&longitude=' + long + '&radius=800&eventcode=LIVE&order=distance&description=1',
                type: "GET",
                success: function(response) {
                    var list = [];
                    $(response).find("results").each(function() {
                        var el = $(this);
                        var obj = {
                            "eventname": el.find("eventname").text(),
                            "imageurl" : el.find("imageurl").text(),
                        };
                        list.push(obj);
                    });
                    callback(list);
                } 
            });
        });
    }
    

    然后使用回调函数调用getEventNearYou

    getEventNearYou(function (events) {
        // code which relies on `events` can be called from here
    });
    

答案 1 :(得分:0)

为4castle的优秀答案添加更多解释。在您编写的代码中,当您在Javascript中调用getLocation()函数时,会发生这种情况:

  1. var latvar long的实例化值为undefined
  2. navigator.geolocation.getCurrentPosition()被调用,需要很长时间才能完成。
  3. 与此同时,Javascript会查找其他内容,然后转到您函数的下一行。
  4. res对象使用latlong的当前未定义值进行实例化。也就是说,res是:{ "lat": undefined, "long": undefined }
  5. callback上调用res函数。这意味着调用了callback latlong的未定义值。
  6. navigator.geolocation.getCurrentPosition()终于完成了它正在做的事情,并将值分配给latlong,但到现在为时已晚,因为已经在未定义的值上调用了回调函数。 / LI>

    在4castle的修订代码中,步骤4-5被放入navigator.geolocation.getCurrentPosition()的匿名回调函数中,这意味着在getCurrentPosition()完成获取位置之前不会执行这些行。