异步,回调,关闭,哦我的

时间:2012-10-22 22:41:45

标签: javascript mongodb dom asynchronous

这是我正在尝试做的事情,并且悲惨地失败了:

我的MongoDB充满了连接到汽车的设备的GPS读数。读数带有时间戳,并有一个lat / lng。

对于每次阅读,我想创建一个包含位置,时间戳和其他信息的Position类。

要在Google地图上绘制此图,我想创建一个Route类,它由一组Positions Objects组成。

顶部的main函数从示例JSON文件加载路径(以避免CSRF问题......另一个故事),创建Position对象并路由对象。当我尝试绘制路线时,问题就开始了。

var positions = this.getPositions();

如果我输入

console.log(positions);

在该行的正下方,它将打印位置数组正常。这需要一点点,因为它很大,但它的工作原理。

但是,如果我输入

console.log(positions[0]);

它不会起作用,因为这些位置还没有加载。

我该怎么办?

我正在使用http://classy.pocoo.org中的classy.js,但我已经证实这不是问题。

function main()
{
    var route = Route('20120928_025650_0');
    route.plot();
}
var Route = Class.$extend({
    __init__ : function(imaging_run_id)  {
        this.imaging_run_id = imaging_run_id;
        this.positions = [];
        this.load();
    },

    getPositions : function() {
        return (this.positions);
    },

    load : function() {
        //var url='http://localhost:5001/gps/by_imaging_run_id/' + this.imaging_run_id;
        var test_url = '/static/20120928_025650_0.json';
        var me = this;
        $.getJSON(test_url, function(route) {
            for(var position in route) {
                var obj = route[position];
                var new_position = Position(obj['_id'], obj['lat'], obj['lng'], obj['timestamp'], obj['epoch_timestamp'], obj['is_valid']);
                me.pushPositions(new_position);
            }
            me.orderPositions();
        })
        .error(function(jqXhr, textStatus, error) {
            alert("ERROR: " + textStatus + ", " + error);
        });
    },

    orderPositions : function() {
        var unsorted_array = this.getPositions();
        var sorted = unsorted_array.sort(function(a,b){ //Custom sort function
            return a['timestamp'] - b['timestamp']; //Sort ascending
        });
        this.setPositions(sorted);
    },

    plot : function() {
        var positions = this.getPositions();
        var points = [];
        var bounds = new google.maps.LatLngBounds();
        for(var i=0; i<positions.length; i++)
        {
            var obj = positions[i];
            var point = new google.maps.LatLng(obj['location'][0], obj['location'][1]);
            points.push(point);
            bounds.extend(point);
        }
        // Create the polyline.
        var route = new google.maps.Polyline({
            path: points,
            strokeColor: '#e81971',
            strokeOpacity: 1.0,
            strokeWeight: 4
        });
        map.fitBounds(bounds);
        route.setMap(map);
    }
});

var Position = Class.$extend({
    __init__ : function(id, lat, lng, timestamp, epoch_timestamp, valid)  {
        this.id = id;
        this.location = [lat, lng];
        this.timestamp = new Date(timestamp);
        this.epoch_timestamp = new Date(epoch_timestamp);
        this.valid = valid;
        this.anchor_location;
    },.....

1 个答案:

答案 0 :(得分:3)

如果我理解正确,你会想做这样的事情:

var positions = this.getPositions(function(positions) {
    console.log(positions[0]);
});

也就是说,你想要以接受单个回调参数的方式编写“getPositions”,一旦位置成功加载就调用该参数,并传递位置数组。在getPositions中,您可以检查位置是否已经加载,如果已加载,则直接调用回调。否则,你将它们添加到一个回调队列(例如this.positionsLoadedCallbacks),在你加载所有位置之后迭代它(我认为这将在load函数附近的某个位置{{1 }})。

例如,您的me.orderPositions()函数可能如下所示:

getPositions

在您确定已加载位置(即在loadJSON成功回调中)后,您需要输入以下内容:

getPositions : function(callback) {
    if(this.positions !== null) {
        callback(this.positions);
        return;
    } 

    this.positionsLoadedCallbacks.push(callback);
},

不要忘记初始化for(var i=0; i < this.positionsLoadedCallbacks.length; i++) { this.positionsLoadedCallbacks[i](this.positions); } :)

console.log trivia

this.positionsLoadedCallbacks的工作原理和console.log(positions)并不容易:如果您将对象引用传递给console.log(positions[0]),则在点击“扩展”时会检查对象箭头并试着看看里面的对象/数组。当你点击那个箭头时,当然已经加载了这些位置。但是,如果您传递特定的数组元素(例如console.log),它将直接尝试查找该值,发现它仍然是positions[0],并将该结果记录在控制台中。

亲自尝试:

undefined

Chrome 24中的上一个代码段在控制台中显示var i = []; console.log([i]); i.push(123); ,但是当我展开它时,它会告诉我该数组为[Array[0]]且其第一个元素为length: 1