2011-02-06 1 views
8

자바 스크립트 코드에서 반복 횟수가 10,000 회를 초과하는 for 루프가 있습니다. for 루프는 < div> 태그를 만들고 현재 페이지 DOM의 상자에 추가합니다. 그 모든 10,000 < 사업부를로드하는 데 너무 많은 시간을 할애하기 때문에자바 스크립트 : 자바 스크립트 코드 실행 사이에 간단한 지연을 넣는 방법은 무엇입니까?

for(i = 0; i < data.length; i++) 
{ 
    tmpContainer += '<div> '+data[i]+' </div>'; 
    if(i % 50 == 0) { /* some delay function */ } 
} 
containerObj.innerHTML = tmpContainer; 

은 내가

/* some delay function */ 

의 장소에서 코드가 될 것입니다 무엇 때문에 매 50 < div> 태그 후 지연을 데려 가고 싶다는> 태그. 나는 상자를 50 < div> 태그의 덩어리로 업데이트하려고합니다.

미리 감사드립니다.

답변

15

이러한 상황에서 편리한 트릭이 있습니다. 0 밀리 초와 함께 setTimeout을 사용하십시오. 이 자바 스크립트가 브라우저에 굴복하게됩니다 (그래서, 그 렌더링을 수행하는 등 사용자 입력에 응답 할 수 있습니다)하지만, 일정 시간 기다려야을 시작하지 않고 :

for (i=0;i<data.length;i++) { 
    tmpContainer += '<div> '+data[i]+' </div>'; 
    if (i % 50 == 0 || i == data.length - 1) { 
     (function (html) { // Create closure to preserve value of tmpContainer 
      setTimeout(function() { 
       // Add to document using html, rather than tmpContainer 

      }, 0); // 0 milliseconds 
     })(tmpContainer); 

     tmpContainer = ""; // "flush" the buffer 
    } 
} 

를 : 티제이 Crowder는 위 코드가 루프의 각 반복에서 불필요한 함수를 생성한다는 점을 아래에서 올바르게 설명합니다 (하나는 클로저를 설정하고 다른 하나는 setTimeout의 인수로 사용함). 이것은 문제가되지는 않겠지 만 원할 경우 한 번만 클로저 함수를 생성하는 his alternative을 확인할 수 있습니다.

경고의 단어 : 위 코드가 더 즐거운 렌더링 경험을 제공하더라도 페이지에 10000 개의 태그가있는 것은 좋지 않습니다. 이 후에는 다른 모든 DOM 조작이 더 느려질 것입니다. 레이아웃을 변경하기 위해 더 많은 요소가 포함되어 있고 훨씬 더 비싼 리플 로우 계산이 필요하기 때문입니다.

+1

두 가지 주석은 작동합니다. 1. 50 div에 도달 할 때마다 ** 새로운 ** 기능이 불필요하게 생성됩니다. 그것은 199 가지의 불필요한 기능입니다. 아마 괜찮 겠지 만 여전히 피할 수있는. 2. 문자열 배열에서 HTML을 만든 다음 문자열 연결을 사용하여 HTML을 빌드하는 것보다'a.join ("")'을 사용하여 완료되면 하나의 큰 문자열을 만드는 것이 더 효율적입니다. –

+0

@ T.J. 당신은 그 두 가지 점에 대해 옳았습니다. 그러나 단순화를 위해 귀찮게하지 않았습니다 : 1. 기능 생성은 거의 성능상의 문제가 아닙니다. 병목 현상이 DOM 일 때 특히 그렇습니다. 2. 문자열 연결은 IE에서만 문제이며, 그리고 종종 다른 브라우저에서 더 빠르지 만 IE의 경우에도 'tmpContainer'를 빈 문자열로 재설정하기 때문에 문자열은 결코 커지지 않습니다.) –

+0

정말 멋진 솔루션입니다. –

2

당신은 몇 가지 코드의 실행을 지연시킬 window.setTimeout 기능을 사용할 수 있습니다

if(i % 50 == 0) { 
    window.setTimeout(function() { 
     // this will execute 1 second later 
    }, 1000); 
} 

을하지만 당신의 자바 스크립트를 실행하는 것입니다. 멈추지 않을거야.

1

나는 함수로 div의를 생성하는 코드를 탈옥, 다음과 같이 주기적으로 setTimeout을 통해 그 함수의 실행을 예약 할 것 :

function createThousands(data) { 
    var index; 

    index = 0; 
    doAChunk(); 

    function doAChunk() { 
     var counter; 

     for (counter = 50; counter > 0; --counter) { 
      // Are we done? 
      if (index >= data.length) { 
       // Yup 
       return; 
      } 

      // ...create a div... 

      // Move to the next 
      ++index; 
     } 

     // Schedule the next pass 
     setTimeout(doAChunk, 0); // 0 = defer to the browser but come back ASAP 
    } 
} 

이 하나의 폐쇄를 사용 doAChunk이 작업을 수행하는 작업. 그 폐쇄는 작업이 끝나면 가비지 수집 대상입니다. (더보기 : Closures are not complicated)

Live example

+0

는 문제를 해결하지 못합니다 –

+0

@fehergeri : *내 문제? 응? –

+0

@fehergeri : 오, 알았어, 당신은 * 그의 문제를 의미했다. 중간 업데이트를하지 않는 문제를 다루었습니다. 리플 로우는 완전히 다른 것입니다. –

1

그것은 리플 로우 때문에 많은 시간이 소요됩니다. 문서 조각을 작성한 다음 자식을 추가해야합니다.

When does reflow happen in a DOM environment?

Javascript Performance - Dom Reflow - Google Article

수면 당신이 innerHTML을하고 innerHTML을 할 수있는 추가 기능을 포함하는 문자열을 생성, 문제 반면에

해결되지 않습니다.문자열은 실제로 큰 성능이 필요하지 않지만, .innerhtml 명령을 실행하면 문자열을 구문 분석하고 요소를 작성하고 추가하는 프로세스가 시작됩니다. 인터럽트를 지연 시키거나 지연을 추가하십시오.

innerhtml 프로세스를 잠자기 또는 중단 할 수 없습니다.

요소를 하나씩 생성하고 50 개의 요소를 추가 한 후에는 settimeout 지연을 만들어야합니다.

var frag = document.createDocumentFragment(); 

function addelements() { 

    var e; 
    for(i=0;i<50;++i) { 
     e = document.createElement('div'); 
     frag.appendChild(e); 
    } 
    dest.appendChild(frag); 
    window.setTimeout(addelements,1000); 

} 
-1

브라우저를 걸지 않고 자바 스크립트에 지연을 넣는 실제 트릭입니다. 당신은 php 페이지를 호출하는 동기식 메서드와 함께 ajax 함수를 사용해야하며, php 페이지에서 sleep() PHP 함수를 사용할 수 있습니다! http://www.hklabs.org/articles/put-delay-in-javascript

+2

[링크 전용 답변] (http://meta.stackoverflow.com/tags/link-only-answers/info)은 권장하지 않으므로 SO 답변은 솔루션 검색의 종점이어야합니다 (시간이 지남에 따라 부실 해지는 경향이있는 참조의 또 다른 중간 기착). 링크를 참조 용으로 유지하면서 독립형 시놉시스를 여기에 추가하는 것을 고려해보십시오. – kleopatra