2008-11-09 6 views
15

이것은 코드가 완벽하게 정상적으로 작동하기 때문에 일종의 두려움에 대한 질문입니다. 내 심미안을 너무 미미하게 자극합니다. 내 자신의 두뇌가 지금 실패하고 있기 때문에 Stack Overflow로 향하고 있습니다.자바 스크립트 콜백 함수 및 재귀

다음은 Google지도 JS API를 사용하여 주소를 검색하고지도에 마커를 배치하는 코드 스 니펫입니다. 그러나 때로는 초기 조회가 실패하므로 다른 주소로 프로세스를 반복하고 싶습니다.

geocoder.getLatLng(item.mapstring, function(point) { 
    if (!point) { 
     geocoder.getLatLng(item.backup_mapstring, function(point) { 
      if (!point) return; 
      map.setCenter(point, 13); 
      map.setZoom(7); 
      map.addOverlay(new GMarker(point)); 
     }) 
     return; 
    } 
    map.setCenter(point, 13); 
    map.setZoom(7); 
    map.addOverlay(new GMarker(point)); 
}) 

은 ( getLatLng에 두 번째 매개 변수는 콜백 함수입니다.) 당신이 센터와지도를 확대하고 마커를 추가 세 줄이 번 주 콜백, 중복 된 것을 볼 수 있습니다 물론

한 번 "폴백 콜백"(하하). 중복되지 않고 모든 것을 표현할 수있는 방법을 찾을 수 있습니까? 귀하의 솔루션이 임의의 수의 백업 맵 문자열에 대해 작동하는 경우 보너스 포인트와 나의 예상을 받게됩니다.

답변

21

다른 답변도 좋지만 한 가지 더 많은 옵션이 있습니다. 이것은 당신이 시작 같은 형태를 유지할 수 있지만 반복적으로 참조 할 수 있도록 람다 함수를 명명의 트릭을 사용

mapstrings = ['mapstring1', 'mapstring2', 'mapstring3']; 

geocoder.getLatLng(mapstrings.shift(), function lambda(point) { 
    if(point) { 
     // success 
     map.setCenter(point, 13); 
     map.setZoom(7); 
     map.addOverlay(new GMarker(point)); 
    } 
    else if(mapstrings.length > 0) { 
     // Previous mapstring failed... try next mapstring 
     geocoder.getLatLng(mapstrings.shift(), lambda); 
    } 
    else { 
     // Take special action if no mapstring succeeds? 
    } 
}) 

기호 "람다"가 사용되는 처음으로, 그것은이다 그것을 새로운 함수 리터럴 이름으로 소개하십시오. 두 번째로 사용 된 경우 재귀 참조입니다.

크롬에서 작동하는 함수 리터럴 이름 지정은 대부분의 최신 브라우저에서 작동한다고 가정합니다. 그러나 테스트하지 않았기 때문에 이전 브라우저에 대해 알지 못합니다.

+0

리터럴 이름 지정이 필요하지 않습니다. 내 솔루션에서 사용한 것을 사용할 수 있습니다 .-- arguments.callee는 함수를 참조합니다. –

+4

리터럴 이름 지정은 솔루션보다 더 깔끔하고 덜 수줍음이긴하지만 –

+0

함수가 arguments.callee를 통해 자신을 참조하는 것을 허용하는 대신 이름을 지정하는 것이 "방법"보다 깔끔합니까? LOL - 나는 이것이 정직하기에 다소 주관적인 것이라고 생각합니다. :) –

1

어때?

function place_point(mapstrings,idx) 
{ 
    if(idx>=mapstrings.length) return; 
    geocoder.getLatLng(mapstrings[idx], 
         function(point) 
         { 
          if(!point) 
          { 
           place_point(mapstrings,idx+1); 
           return; 
          } 
          map.setCenter(point, 13); 
          map.setZoom(7); 
          map.addOverlay(new GMarker(point)); 
         }); 
} 

원하는만큼 많은 백업 문자열. 첫 번째로 두 번째 인수로 0을 사용하여 호출하십시오. 함수에

2

그래, 요소 그것을 밖으로 :)

geocoder.getLatLng(item.mapstring, function(point) { 
    if (!point) { 
     geocoder.getLatLng(item.backup_mapstring, function(point) { 
       if (point) { 
        setPoint(point); 
       } 
     }) 
     return; 
    } 

    function setPoint(point) { 
     map.setCenter(point, 13); 
     map.setZoom(7); 
     map.addOverlay(new GMarker(point)); 
    } 

    setPoint(point); 
}); 
8

명시 적으로 재귀를 지원하지 않는 언어 구조에서 재귀를 수행하기위한 대단히 좋은 방법이있다는 고정 소수점 콤비을했다. 가장 잘 알려진 것은 Y-Combinator입니다.

Here is the Y combinator for a function of one parameter in Javascript

:

function Y(le, a) { 
    return function (f) { 
     return f(f); 
    }(function (f) { 
     return le(function (x) { 
      return f(f)(x); 
     }, a); 
    }); 
} 

이 조금 무서운 보이지만, 한 번만 저를 작성해야합니다. 실제로 사용하는 것은 꽤 간단합니다. 기본적으로 한 매개 변수의 원래 람다를 가져 와서 두 매개 변수의 새로운 함수로 바꿉니다. 첫 번째 매개 변수는 재귀 호출을 수행 할 수있는 실제 람다 식이며 두 번째 매개 변수는 원래 첫 번째 매개 변수입니다 (point)를 사용하십시오.

다음은이 예제에서 사용하는 방법입니다. 조회 할 문자열 목록으로 mapstrings을 사용하고 있으며 pop 함수는 머리에서 요소를 파괴적으로 제거합니다.

geocoder.getLatLng(pop(mapstrings), Y(
    function(getLatLongCallback, point) 
    { 
    if (!point) 
    { 
     if (length(mapstrings) > 0) 
     geocoder.getLatLng(pop(mapstrings), getLatLongCallback); 
     return; 
    } 

    map.setCenter(point, 13); 
    map.setZoom(7); 
    map.addOverlay(new GMarker(point)); 
    });