JavaScript将数组推入另一个数组

6

我目前正在使用Google地图的地理编码,并需要创建包含多个数组的数组。

基本上,我需要创建这样一个数组:

    var locations = [
      ['Bondi Beach', -33.890542, 151.274856, 4],
      ['Coogee Beach', -33.923036, 151.259052, 5],
      ['Cronulla Beach', -34.028249, 151.157507, 3],
      ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
      ['Maroubra Beach', -33.950198, 151.259302, 1]
    ];

但是需要动态操作!我需要这个数组来在地图上标记位置。

我的操作:

        var locations = []; // The initial array
        for (var i = 0; i < addresses.length; ++i){

            var address=addresses[i]; // the address e.g. 15 Main St, Hyannis, MA
            geocoder.geocode({ 'address': address}, function(results){
                var obj = {
                    0: address,
                    1: results[0].geometry.location.hb,
                    2: results[0].geometry.location.ib,
                    3: i
                };
                console.log(obj);
                locations.push(new Array());
                locations[i].push(obj);

            });
        };

        console.log(locations.length);

问题,疑问:

我没有看到任何错误,但最终locations[]数组为空。

如果需要,这里是控制台屏幕截图:


3
geocode 是异步的。在处理数组之前,您需要等待所有调用都有响应。 - Prinzhorn
嗯,我以为循环应该结束才能让脚本继续运行呢?不是吗? - rinchik
将一个空数组推入另一个数组的基本方法在这个问题中并不明显,因此我要指出对于一个数组来说,它是myArray.push(new Array())myArray必须至少被实例化为一个空数组,例如myArray = [] - Chris Halcrow
2个回答

2
这是你所需的全部内容:
geocoder.geocode({ 'address': address}, function(results){
            locations.push([
              address,
              results[0].geometry.location.hb,
              results[0].geometry.location.ib,
              i //this is actually going to always be 
                //addresses.length because the callback won't fire
                //until well after the loop has completed. 
                //Is this really a necessary field to have 
                //in your array? if so, you'll need to refactor a bit
            ]);
        });

有道理,但是console.log(locations.length);仍然显示0 - rinchik
2
@rinchik 可能是因为 geocoder.geocode() 是异步的... 当你记录它时,locations 还没有改变。 - canon
看看 Prinzhorn 在你的问题下面的评论...它是异步的,你需要在所有地理编码完成后才触发 console.log - BLSully
1
@BLSully 你应该提到,由于作用域的原因,i 的值将始终为 addresses.length - t.niese

1
我没有时间测试代码,但它应该能按照以下方式工作:
    function requestLocations( addresses, callback ) {
        var remainingLocations = addresses.length;
        var locations = [];

        for (var i = 0; i < addresses.length; ++i){

            var address=addresses[i]; // the address e.g. 15 Main St, Hyannis, MA

            locations[i] = [];

            geocoder.geocode({ 'address': address}, (
                function(idx) {
                    return function(result) {
                        locations[idx] = [  addresses[idx], 
                                            results[0].geometry.location.hb,
                                            results[0].geometry.location.ib,
                                            idx
                                        ];

                        //decrement the number of remaining addresses
                        --remainingLocations;

                        //if there are no more remaining addresses and a callback is provided then call this calback with the locations
                        if( remainingLocations === 0 && callback ) {
                            callback(locations);
                        }               
                    }; // returns the real callback function for your geocoding

                })(i) //direct invocation of function with paramter i for scoping
            );

        }
    }


    requestLocations(addresses, function( locations ) {
        console.dir(locations);
        console.log(locations.length);
    });

您的代码存在以下问题。首先,执行了代码的这部分内容:
        var locations = []; // The initial array
        for (var i = 0; i < addresses.length; ++i) {

            var address = addresses[i]; // the address e.g. 15 Main St, Hyannis, MA
            geocoder.geocode({
                'address': address
            }, function(results) {
                //this part is called later when that data is ready (it is an asynchronous callback)

            });
        };

        //because of the async request this is still 0
        console.log(locations.length);

之后,一旦浏览器从服务器接收到数据,回调函数本身就会被调用:

      function(results) {
        var obj = {
            0: address,
            1: results[0].geometry.location.hb,
            2: results[0].geometry.location.ib,
            3: i
        };
        console.log(obj);
        locations.push(new Array());
        locations[i].push(obj);

      }

太棒了! :D 刚刚测试过了!它能正常工作!感谢您详细的回答和对我的代码的工作 :) +1 - rinchik
1
@rinchik,代码中有一个错误,回调函数中的addresse应该是addresses[idx]。请重新检查你的代码,否则你的结果中将始终只有同一个地址。 - t.niese
嗯...快速问题!由于某种原因,对于(var i = 0; i < addresses.length; ++i)循环只循环了12次,然后停止了。如果我在这里放置console.log(remainingLocations); 这是输出:http://screencast.com/t/ENbhFdpaDRcE 你有任何想法为什么会发生这种情况吗? - rinchik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接