2012-05-30 5 views
1

나는 사소한 것을 묻는 것이 어리석은 짓을하지만 실제로는 모범 사례 응답을 원한다. (나는 그게 가능하지 않다면 "setTimeout"해결책을 찾지 않을 것이다.).자바 스크립트 콜백 타이밍

빠른보기 : 콜백 내에서 푸시 할 배열이 있습니다. 배열을 채운 다음 콜백 외부에서 사용하고 싶습니다.

실용 : 나는 도시의 배열을 가지고 있는데, 나는 그것들을 Google의 API로 지오 코딩하고 배열을 결과 LatLng으로 모두 채우고 싶다. 나중에 나는 그들과 함께 표식 개체를 만들고, 그것을 클러스터러에 추가 할 것이다.

coder = new google.maps.Geocoder(); 
$places = ['Truro, NS', 'Halifax, NS', 'Sydney, NS', 'Dartmouth, NS']; 
all_the_pins = Array(); 
for(i in $places){ 
    var $place = $places[i]; 
    coder.geocode({address:$place}, function(res, stat){ 
     switch(stat){ 
      case 'OK': 
       all_the_pins.push(res[0].geometry.location); 
       break; 
     } 
    }); 
} 
console.log(all_the_pins); 

편집이 :이 문제를 명확히하기 위해 : 당신은 콜백 내에서 all_the_pins을 조사한다면 을 문제는 all_the_pins 변수가 글로벌인지 아닌지 여부 또는 범위의 문제가 아닙니다, 당신은 그것을 볼 것이다 동일한 변수 (푸시 할 변수)입니다. 문제는 콜백 내에서 푸시가 발생하기 때문에 console.log이 실행되기 전에 발생하지 않는다는 것입니다.

+0

무엇이 문제입니까? 당신의 위치는'all_the_pins' 배열에 누적 될 것입니다. 배열을 전역 적으로 선언하면 전역 적으로 사용할 수 있습니다. – jfriend00

+0

단순히 배열을 전역 var로 선언 하시겠습니까? 'var all_the_pins = [];'문서 상단에 있습니다. 모든 범위에서 액세스 할 수 있습니다. –

+0

나는 동의한다, 나는 그 질문을 이해하지 못한다 ... – Jonathan

답변

0

나머지 코드는 다른 콜백 안에 살 수 있습니까? x 번 (즉, 입력 배열의 길이) 호출 된 후에 만 ​​실행되는 함수를 설정합니다. 귀하의 질문이 명확하지 않기 때문에

coder = new google.maps.Geocoder(); 
$places = ['Truro, NS', 'Halifax, NS', 'Sydney, NS', 'Dartmouth, NS']; 
all_the_pins = Array(); 

function myCallback(count, totalCount, all_the_pins) { 
    if (count != totalCount) return; 

    console.log(all_the_pins); 
} 

count = 1; 

for(i in $places){ 
    var $place = $places[i]; 
    coder.geocode({address:$place}, function(res, stat){ 
     switch(stat){ 
      case 'OK': 
       all_the_pins.push(res[0].geometry.location); 

       myCallback(count, $places.length, all_the_pins); 
       count++; 
       break; 
     } 
    }); 
} 
+0

배열에서 for-in-loops를 사용하지 마십시오. – Bergi

+0

나는 코드의 나머지 부분을 복사하고 있었다. 콜백 설정에 대한 대답이었다. – freejosh

1

, 난 당신이 모든 지오 호출이 완료 될 때 all_the_pins array을 처리 할 것으로 짐작됩니다. 지오 코드 함수 호출은 비동기식이므로 모든 지오 코드 호출이 완료된 시점을 추적하고 마지막 배열을 사용할 수 있어야합니다.

그렇다면, 당신은 이런 그 작업을 수행 할 수 있습니다

var coder = new google.maps.Geocoder(); 
var $places = ['Truro, NS', 'Halifax, NS', 'Sydney, NS', 'Dartmouth, NS']; 
var all_the_pins = Array(); 
var remaining = $places.length; 
for (var i = 0, len = $places.length; i < len; i++) 
    var $place = $places[i]; 
    coder.geocode({address:$place}, function(res, stat){ 
     switch(stat){ 
      case 'OK': 
       all_the_pins.push(res[0].geometry.location); 
       break; 
     } 
     --remaining; 
     if (remaining == 0) { 
      // all_the_pins data is set here 
      // call a function and pass the array to it or put your 
      // code here to process it 
      console.log(all_the_pins); 
     } 
    }); 
} 

참고 : 나는 또한 배열을 반복하기위한 for 루프의 적절한 형태로 변경되었습니다. for (var i in xxx)은 객체의 속성을 반복하기위한 것이지 배열의 요소는 아닙니다.

1

아니요, setTimeout은 여기에서 전혀 쓸모가 없습니다. 비동기식 요청이 여러 개 있고 모든 요청이 콜백되었을 때 무언가를하고 싶다면 카운터 만 가능합니다. 마지막 콜백 후 열린 요청의 수는 null로 떨어집니다. 원하는 것을 실행하십시오.

var coder = new google.maps.Geocoder(); 
var places = ['Truro, NS', 'Halifax, NS', 'Sydney, NS', 'Dartmouth, NS']; 
var all_the_pins = []; 
for (var i=0; i<places.length) 
    coder.geocode({address:places[i]}, function(res, stat){ 
     if (stat == 'OK') 
      all_the_pins.push(res[0].geometry.location); 
     else 
      all_the_pins.push(stat); 

     // counter is length of results array: 
     if (all_the_pins.length >= places.length) { 
      console.log(all_the_pins); 
     } 
    });