简体   繁体   English

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

[英]Variables are being bound to the callback of a getCurrentLocation function. Why isn't this closure working?

I apologize for the amount of code, but I think this is actually a problem with AppMobi's getCurrentLocation function. 我为代码量道歉,但我认为这实际上是AppMobi的getCurrentLocation函数的一个问题。 Basically what happens is I delegate a tap event to each list element. 基本上发生的是我将tap事件委托给每个列表元素。 Then when you tap it, it runs an asynchronous getCurrentLocation and updates some stuff. 然后当你点击它时,它运行一个异步的getCurrentLocation并更新一些东西。 Then the next time you tap another list element, the variables bound in the callback of the getCurrentLocation Function only refer to the first time it was called. 然后,当您下次点击另一个列表元素时,getCurrentLocation函数的回调中绑定的变量仅引用它第一次被调用。 Why doesn't this work?? 为什么不工作?

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

Well, your issue seems to be that you are declaring a private variable event_index inside the check_in function and try to resolve it's value by accessing a global event_index variable inside onLocationFound . 好吧,你的问题似乎是你在check_in函数中声明了一个私有变量event_index ,并尝试通过访问onLocationFound的全局event_index变量来解析它的值。

Here's what you could do instead: 这是你可以做的事情:

AppMobi.geolocation.getCurrentPosition(function (response) {
   onLocationFound(response, event_index);
}, errorFunction);

function onLocationFound(response, event_index) { //... }

EDIT: 编辑:

it is declared within check_in... 它在check_in中声明...

You are right, I totally missed that somehow. 你是对的,我完全错过了。 Well in that case it's very unlikely that the event_index variable inside onLocationFound isin't the same as in check_in . 那么在这种情况下,这是非常不可能的event_index内部变量onLocationFound isin't一样check_in Do a console.log(event_index) inside onLocationFound and it should be the same. onLocationFound执行console.log(event_index) ,它应该是相同的。 The only way it could be different is if you modify the local variable before the handler is called, which you doesn't seem to do, or if getCurrentPosition stores the first handler somehow and ignores subsequent handlers, but this API wouldn't make any sense. 唯一可能不同的方法是,如果在调用处理程序之前修改局部变量,您似乎没有这样做,或者getCurrentPosition以某种方式存储第一个处理程序并忽略后续处理程序,但此API不会生成任何感。

EDIT 2: 编辑2:

As we suspect the handler might not be registered correctly the second time, I would suggest to check this way: 由于我们怀疑第二次处理程序可能没有正确注册,我建议以这种方式检查:

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

    //...

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

You can also simple do onLocationFound.version = new Date() and check arguments.callee.version to see if it stays the same. 你也可以简单地做onLocationFound.version = new Date()并检查arguments.callee.version以查看它是否保持不变。

I know you marked this answered already but....it might not actually be a problem with the library. 我知道你已经标记了这个已经回答了但是....它可能实际上不是库的问题。 Can I direct you to a post by @Joel Anair where he has posted an article and the example number five seems to be the "gotcha" which might have gotcha ;) 我可以引导你到@Joel Anair的一篇文章,他发表了一篇文章,第五个例子似乎是可能有问题的“陷阱”;)

How do JavaScript closures work? JavaScript闭包如何工作?

Basically in the for loop they are all being set to the same reference of i so event_index will all be the same value/reference. 基本上在for循环中,它们都被设置为i的相同引用,因此event_index将是相同的值/引用。 (which explains why they're all the same). (这解释了为什么他们都是一样的)。

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

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