简体   繁体   English

Javascript异步功能:回调不起作用

[英]Javascript asynchronous function: callback not working

I am trying to return a result from an asynchronous function in Javascript. 我正在尝试从Javascript中的异步函数返回结果。

I have seen this question: How do I return the response from an asynchronous call? 我已经看到了这个问题: 如何从异步调用返回响应? , and I am trying to implement the callback solution, but something is wrong. ,而我正在尝试实现回调解决方案,但是出了点问题。

This is my code: 这是我的代码:

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

Basically, I want to find my current location, and create a HTTP get request to www.skiddle.com to retrieve events near that location. 基本上,我想找到我的当前位置,并向www.skiddle.com创建HTTP get请求以检索该位置附近的事件。

This is how I call the function: 这就是我所谓的函​​数:

var x = getEventNearYou();

but I seem to have made a mistake, since I am getting the bad request error ( lat and long are undefined). 但是我似乎犯了一个错误,因为我遇到了错误的请求错误(未定义latlong )。

You're using callbacks in a way that undermines their usefulness. 您使用回调的方式会削弱其用途。 You're still writing your code in a synchronous style. 您仍在以同步样式编写代码。 You should continue to reference: How do I return the response from an asynchronous call? 您应该继续参考: 如何从异步调用返回响应?

In the mean time, I'll restructure your code to show how it's done. 同时,我将重组您的代码以显示其完成方式。

  1. As a rule of thumb, if any of the code inside a function uses callbacks, that outer function also needs to accept a callback as a parameter. 根据经验,如果函数内的任何代码使用回调,则该外部函数也需要接受回调作为参数。

  2. If a variable is given a value inside a callback function, it won't be defined outside of the callback function (because asynchronous code always runs after synchronous code). 如果在回调函数中为变量赋值,则不会在回调函数之外定义该变量(因为异步代码始终同步代码之后运行)。

  3. Don't use async: false 不要使用async: false

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

Then call getEventNearYou using a callback function: 然后使用回调函数调用getEventNearYou

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

Just adding a bit more explanation to 4castle's excellent answer. 只是在4castle的出色答案中添加了更多解释。 In the code you wrote, when your getLocation() function is called in Javascript, this is what will happen: 在您编写的代码中,用Javascript调用getLocation()函数时,将发生以下情况:

  1. var lat and var long are instantiated with values of undefined . var latvar longundefined值实例化。
  2. navigator.geolocation.getCurrentPosition() is called, which takes a long time to complete. 调用navigator.geolocation.getCurrentPosition()会花费很长时间。
  3. In the meantime, Javascript looks for something else to do and moves to the next lines in your function. 同时,Javascript寻找其他事情要做,并移至函数的下一行。
  4. The res object is instantiated with the current undefined values of lat and long . 使用当前未定义latlong实例化res对象。 That is, res is: { "lat": undefined, "long": undefined } 也就是说, res是: { "lat": undefined, "long": undefined }
  5. The callback function is called on res . callback函数在res上调用。 This means callback is called with undefined values for lat and long . 这意味着使用latlong未定义值callback
  6. navigator.geolocation.getCurrentPosition() finally finishes what it was doing and assigns values to lat and long , but by now it is too late because your callback function was already called on the undefined values. navigator.geolocation.getCurrentPosition()最终完成了所要做的工作,并将值分配给latlong ,但是现在为时已晚,因为您的回调函数已经在未定义的值上调用了。

In 4castle's revised code, steps 4-5 are put inside an anonymous callback function to navigator.geolocation.getCurrentPosition() , which means these lines won't be executed until getCurrentPosition() is finished getting the position. 在4castle的修改后的代码中,步骤4-5被放置在navigator.geolocation.getCurrentPosition()的匿名回调函数中,这意味着直到getCurrentPosition()完成获取位置后,这些行才会执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM