变量被绑定到getCurrentLocation函数的回调。为什么关闭不起作用?

时间:2013-09-10 01:03:29

标签: javascript geolocation closures appmobi

我为代码量道歉,但我认为这实际上是AppMobi的getCurrentLocation函数的一个问题。基本上发生的是我将tap事件委托给每个列表元素。然后当你点击它时,它运行一个异步的getCurrentLocation并更新一些东西。然后,当您下次点击另一个列表元素时,getCurrentLocation函数的回调中绑定的变量仅引用它第一次被调用。为什么这不起作用?

app = { events: [{text: "foo", time: new Date()}, {text: "bar", time: new Date()}] };
$(document).ready(refreshEvents);

function refreshEvents() {
    for (var index in app.events) {
        insertEventHTML(app.events[index]);
    }
}

function insertEventHTML(event) {
    var text = event.text;
    var time = event.time;

    var new_element = $('<li class="event_element"></li>');
    var new_checkin_element = $('<div class="check_in_button"></div>');

    new_checkin_element.bind('tap', function(e) {
        check_in(e);
        fade($(this), 1.0);
    });
    new_element.append(new_checkin_element);

    var text_element = $('<div class="text_element">' + text + '</div>');
    new_element.append(text_element);
    var time_element = $('<div class="time_element">' + time + '</div>');
    new_element.append(time_element);
    $('#your_events').append(new_element);
}

function check_in(e) {
    $(e.target).siblings('.time_element').text('just now');
    var time = new Date();                   // time and event_index are the trouble variables here
    var event_index = getEventIndex(e);      // the first time this function runs, event_index is correct
                                             // then each subsequent time, it remains the same value as the first
    if (!app.settings.use_location) {
        app.events[event_index].times.unshift({time: time, location: null});
    } else {
        AppMobi.geolocation.getCurrentPosition(onLocationFound, errorFunction);
    }

    function onLocationFound(response) {    
        var lat = response.coords.latitude;
        var lon = response.coords.longitude;
        var last_time = app.events[event_index].times[0];

        if (last_time != undefined && last_time.time == time) {
            // event_index and time here will only ever refer to the first time it was called.  WHY??? 
            add_checkin(response, event_index, time);        
        }else{
            console.log('onLocationFound was called twice');
        }
    }

    function errorFunction(error) {
        $.ui.popup({title: 'geolocation error', message: 'Geolocation error.  Turn off location services in settings.'});
    }

    function add_checkin(response, event_index, time) {
        // and then of course event_index and time are wrong here as well.  I don't get it.
        app.events[event_index].times.unshift(
        {
            time: time, 
            location: {
                latitude: response.coords.latitude,
                longitude: response.coords.longitude
            }
        });
        AppMobi.cache.setCookie('app', JSON.stringify(app), -1);
    }
}

function getEventIndex(e) {
    var target = $(e.target).parent();
    var siblings = target.parent().children('li');
    for (var i = 0; i < siblings.length; i++) {
        if ($(target)[0].offsetTop == $(siblings[i])[0].offsetTop) {
            return i;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

好吧,您的问题似乎是您在event_index函数中声明了一个私有变量check_in,并尝试通过访问{{1}内的全局event_index变量来解析它的值}}

以下是您可以做的事情:

onLocationFound

编辑:

  

它在check_in ...

中声明

你是对的,我完全错过了。那么在这种情况下,AppMobi.geolocation.getCurrentPosition(function (response) { onLocationFound(response, event_index); }, errorFunction); function onLocationFound(response, event_index) { //... } 内的event_index变量与onLocationFound中的check_in变量不太相同。在console.log(event_index)onLocationFound,它应该是相同的。唯一不同的方法是,如果在调用处理程序之前修改局部变量,而您似乎没有这样做,或者getCurrentPosition以某种方式存储第一个处理程序并忽略后续处理程序,但此API不会没有任何意义。

编辑2:

由于我们怀疑第二次处理程序可能没有正确注册,我建议以这种方式检查:

function check_in() {
    if (!check_in.called) {
        check_in.called = true;
        check_in.onLocationFound = onLocationFound;
    }

    //...

    function onLocationFound() {
        console.log(arguments.callee === check_in.onLocationFound);
    }
}

您也可以简单地执行onLocationFound.version = new Date()并检查arguments.callee.version以查看它是否保持不变。

答案 1 :(得分:1)

我知道你已经标记了这个已经回答但是....它可能实际上不是库的问题。我可以将你引导到@Joel Anair的帖子,在那里他发表了一篇文章,第五个例子似乎是可能有问题的“问题”;)

How do JavaScript closures work?

基本上在for循环中,它们都被设置为i的相同引用,因此event_index将是相同的值/引用。 (这解释了为什么他们都是一样的)。