异步,回调,封闭,噢,我的 [英] Async, Callbacks, Closure, Oh My

查看:96
本文介绍了异步,回调,封闭,噢,我的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面就是我试图做的,在惨遭失败:

我有一个的MongoDB填充有GPS的读数从附连到汽车的装置。读数时间戳,有一个纬度/经度。

对于每个读书,我想创建一个包含位置,时间戳以及其他一些信息的位置类。

要绘制这样的谷歌地图,我想创建一个路由类,它是由放置对象的数组中。

在顶部的主函数加载从样品JSON文件的路径(避免CSRF问题......另一回事),创建位置对象和路由对象罚款。当我尝试绘制路线的问题开始。

  VAR位置= this.getPositions();

如果我键入

 的console.log(职位);

正下方那行,它将打印位置阵列的罚款。这需要一点要做到这一点,因为它是大的,但它的作品。

但是,如果我键入

 的console.log(位置[0]);

它不会工作,因为职位尚未加载。

我该怎么办?

我使用classy.js从 http://classy.pocoo.org 的,但我已经验证这是不符合这样的问题:

 函数main()
{
    VAR路径=路径('20120928_025650_0');
    route.plot();
}
VAR路线=类。$扩展({
    __init__:功能(imaging_run_id){
        this.imaging_run_id = imaging_run_id;
        this.positions = [];
        this.load();
    },    getPositions:功能(){
        返回(this.positions);
    },    载:函数(){
        // VAR URL =的http://本地主机:5001 / GPS / by_imaging_run_id /'+ this.imaging_run_id;
        VAR test_url ='/static/20120928_025650_0.json';
        VAR我=这;
        $ .getJSON(test_url,功能(路线){
            对于(三层VAR位置){
                VAR OBJ =路径[位置]
                VAR new_position =位置(OBJ ['_ ID'],则obj ['纬度'],则obj ['LNG'],则obj ['戳'],则obj ['epoch_timestamp'],则obj ['is_valid']);
                me.pushPositions(new_position);
            }
            me.orderPositions();
        })
        .error(功能(jqXhr,textStatus,错误){
            警报(错误:+ textStatus +,+误差);
        });
    },    orderPositions:功能(){
        变种unsorted_array = this.getPositions();
        VAR分类= unsorted_array.sort(功能(A,B){//定义排序功能
            返回['时间戳'] - B ['时间戳']; //(升序)
        });
        this.setPositions(排序);
    },    剧情:功能(){
        VAR位置= this.getPositions();
        VAR点= [];
        VAR边界=新的google.maps.LatLngBounds();
        对于(VAR I = 0; I< positions.length;我++)
        {
            VAR OBJ =位置[I]
            VAR点=新google.maps.LatLng(OBJ ['位置'] [0],则obj ['位置'] [1]);
            points.push(点);
            bounds.extend(点);
        }
        //创建折线。
        VAR路线=新google.maps.Polyline({
            路径:点,
            则strokeColor:#e81971,
            strokeOpacity,用于:1.0,
            strokeWeight,用于:4
        });
        map.fitBounds(边界);
        route.setMap(地图);
    }
});VAR位置=类。$扩展({
    __init__:功能(ID,纬度,经度,时间戳,epoch_timestamp,有效){
        this.id = ID;
        this.location = [纬度,经度]
        this.timestamp =新的日期(时间戳);
        this.epoch_timestamp =新的日期(epoch_timestamp);
        this.valid =有效;
        this.anchor_location;
    } .....


解决方案

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

  VAR位置= this.getPositions(功能(位置){
    的console.log(位置[0]);
});

这是,你会想,它曾经接受的位置已成功加载时调用一个回调参数的方式来写getPositions,并传递的位置阵列。在 getPositions 可以检查位置已经被加载,并且如果是,直接调用回调。否则,你将它们添加到回调队列(如 this.positionsLoadedCallbacks ),通过它你遍历所有的位置都被加载后,(我认为这将是某处附近你的负荷函数me.orderPositions())。

例如,你的 getPositions 函数可能是这样的:

  getPositions:函数(回调){
    如果(this.positions!== NULL){
        回调(this.positions);
        返回;
    }    this.positionsLoadedCallbacks.push(回调);
},

您确定的位置已经被加载后的某个位置(即在loadJSON成功回调),你需要把这样的事情:

 为(VAR I = 0; I< this.positionsLoadedCallbacks.length;我++){
    this.positionsLoadedCallbacks [I](this.positions);
}

不要忘了初始化 this.positionsLoadedCallbacks :)

的console.log琐事

这是的console.log(职位)作品和的console.log(位置[0])做的原因不是很简单:如果你传递的对象引用的console.log ,当你点击的小展开箭头并尝试看看<对象将被检查EM>在的对象/数组。到时候你单击箭头的位置已加载的,当然。不过,如果你传递一个特定的数组元素(如位置[0] ),这将直接尝试查找该值时,发现它仍然是未定义,并记录导致在控制台中。

自己尝试一下:

  VAR I = [];
([I])的console.log;
i.push(123);

在previous片断,铬24,显示 [数组[0] 在控制台中,但是当我展开它,它告诉我,该数组为长度:1 键,它的第一个元素是 123

Here's what I'm trying to do, and failing miserably at:

I have a MongoDB filled with GPS readings from a device attached to a car. The readings are timestamped and have a lat/lng.

For each reading, I want to create a Position class that contains location, timestamp and some other information.

To plot this on Google Maps, I want to create a Route class, which is made up of an array of Positions Objects.

The main function at the top loads a route from a sample JSON file (to avoid CSRF problems... another story), creates the Position objects and route object fine. The problems start when I try to plot the route.

var positions = this.getPositions();

If I type

console.log(positions);

right below that line, it will print the positions array fine. It takes a bit to do that since it's large, but it works.

If however, I type

console.log(positions[0]);

it wont work because the positions haven't loaded yet.

What do I do?

I'm using classy.js from http://classy.pocoo.org but I've verified this isn't a problem with that.

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

解决方案

If I understand it correctly, you will want to do something like this:

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

That is, you'll want to write "getPositions" in a way that it accepts a single callback parameter which is invoked once the positions have loaded successfully, and is passed the positions array. In getPositions you could check if the positions have already been loaded, and if so, directly invoke the callback. Otherwise, you'll add them to a queue of callbacks (e.g. this.positionsLoadedCallbacks), through which you iterate after all positions have been loaded (I think that would be somewhere in your load function near me.orderPositions()).

For example, your getPositions function might look like this:

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

    this.positionsLoadedCallbacks.push(callback);
},

Somewhere after you are sure the positions have been loaded (i.e. in the loadJSON success callback) you'll need to put something like this:

for(var i=0; i < this.positionsLoadedCallbacks.length; i++) {
    this.positionsLoadedCallbacks[i](this.positions);
}

And don't forget to initialize this.positionsLoadedCallbacks :)

console.log trivia

The reason that console.log(positions) works and console.log(positions[0]) does not is easy: if you pass an object reference to console.log, the object will be inspected when you click on the little "expand" arrow and try to take a look inside the object/array. By the time you click that arrow, the positions have been loaded, of course. However, if you pass a specific array element (e.g. positions[0]) it will directly try to look that value up, find that it is still undefined, and record that result in the console.

Try it yourself:

var i = [];
console.log([i]);
i.push(123);

The previous snippet, in chrome 24, shows [Array[0]] in the console, but when I expand it, it tells me that the array as length: 1 and that its first element is 123

这篇关于异步,回调,封闭,噢,我的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆