4

В настоящее время я работаю с геокодированием карт Google и вам необходимо создать массив, который будет содержать массивы в качестве элементов.JavaScript push Array в массив

В принципе, мне нужно, чтобы создать это:

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

Проблема, вопрос:

Я не вижу каких-либо ошибок, но в конечных точках [] массив пуст.

Вот экран консоли, если это необходимо:

+3

'geocode' является асинхронной. Перед обработкой массива вам нужно подождать, пока ВСЕ вызовы ответят. – Prinzhorn

+0

Hm. Я думал, цикл должен быть закончен для продолжения скрипта? нет? – rinchik

ответ

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

     } 
+0

Awesome! : D Просто испытал это! ОНО РАБОТАЕТ! Спасибо за подробный ответ и работу над моим кодом :) +1 – rinchik

+1

@rinchik была ошибка в нем 'addresse' должно было быть' address [idx] 'в обратном вызове. повторите проверку кода, иначе вы всегда будете иметь тот же адрес в своем результате. –

+0

yep, я заметил :) Большое спасибо! – rinchik

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 
      ]); 
     }); 
+0

Делает смысл ... но console.log (locations.length); по-прежнему показывает 0 – rinchik

+2

@rinchik, вероятно, потому что 'geocoder.geocode()' is async ... и 'locations' не изменился к моменту его регистрации. – canon

+0

См. Комментарий Prinzhorn по вашему вопросу ... это асинхронный, вам нужно только запустить 'console.log' после завершения всех геокодов – BLSully