sleep ()의 JavaScript 버전은 무엇입니까?


2335

sleep다음 pausecomp함수 ( 여기에서 가져온 것)보다 JavaScript에서을 엔지니어링하는 더 좋은 방법이 있습니까?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

이것은 JavaScript에서 Sleep 의 복제본이 아닙니다 -동작 사이의 지연 ; 함수 중간에 실제로 잠을 자고 코드 조각이 실행되기 전에 지연되지 않기를 원합니다 .


4
내가 과정을 계속 결국 동시에 실행과 자신 사이의 동시성의 비트를 만드는 것보다 setTimeouts 대기 할 동안의 setTimeout 사용하는 경우는, 잠시 동안의 중간에 세트입니다
fmsf

159
이것은 끔찍한 해결책입니다. 아무것도하지 않고 처리주기를 씹을 수 있습니다.
26 중 17

12
휴면의 유일한 목적은 콜백을 폴링하거나 기다리는 것입니다. setInterval 및 setTimeout은 이보다 더 좋습니다.
annakata

1
아마도 JavaScript에서 연속 전달 스타일을 사용하여 원하는 것을 할 수 있습니다. 이 기사를
Ognyan Dimitrov

답변:


2559

2017 — 2019 업데이트

이 질문이 제기 된 2009 년 이후로 JavaScript는 크게 발전했습니다. 다른 모든 답변은 이제 더 이상 사용되지 않거나 지나치게 복잡합니다. 현재 모범 사례는 다음과 같습니다.

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

이거 야. await sleep(<duration>).

또는 단일 라이너로 :

await new Promise(r => setTimeout(r, 2000));

참고

  1. awaitasync키워드가 접두사로 사용 되거나 일부 환경 (예 : Chrome DevTools 콘솔 또는 Runkit)에서 스크립트 의 최상위 수준 에서만 실행될 수 있습니다 .
  2. await현재 async기능 만 일시 정지

두 가지 새로운 JavaScript 기능이이 "잠자기"기능을 작성하는 데 도움이되었습니다.

적합성

당신이 (도달 노드보다 오래된 7 사용하고 어떤 이상한 이유로 경우 의 수명을 ), 또는 오래된 브라우저를 대상으로, async/ await여전히를 통해 사용할 수 있습니다 바벨 (도구를 것 transpile 평범한 구식 자바 스크립트로 자바 스크립트 + 새로운 기능) transform-async-to-generator플러그인 과 함께 .


5
여기 좋은 물건. JS가 "절전"모드를 호출 한 후 이것이 최신 브라우저 "활성"/ "비활성"상태에 어떤 영향을 미치거나 관련이 있는지 궁금합니다. 브라우저가 일반 JS에 대해 예상대로 휴면을 차단할 수 있습니까? 나중에 "활성"상태가되면 다시 호출하거나 다른 동작을합니까?
Andre Canilho

18
이에 대한 현재 브라우저 지원은 무엇입니까? 이 솔루션이 대부분의 브라우저 또는 적어도 모든 공통 브라우저에서 지원 될 때까지 이전 솔루션을 "폐기"한 것으로 간주하지 않습니다. 반대로, 나는이 솔루션이 광범위하게 지원 될 때까지 흥미롭지 만 쓸모없고 실용적이지 않다고 생각합니다.
Alvin Thompson

74
이것은 "실제 수면"이 아니며 질문에 대답하지 않습니다. 요청한 사람은 stackoverflow.com/questions/758688/sleep-in-javascript 와 그의 질문을 분명히 구분 했습니다. 실제 절전 모드에서는 다른 스레드가 아닌 한 다른 코드를 실행할 수 없습니다. 이 답변은 다른 질문에 좋습니다.
niry

4
@jacroe-트랜스 필러는 화살표 기능과 비동기 / 대기 (IE가 피를 토하게하는 원인)를 처리합니다.
Jaromanda X

11
단일 스레드 언어 인 @niry JavaScript는 UI와 동일한 스레드에서 실행되며 응답하지 않는 웹 페이지를 유발할 수 있으므로 "실제"절전에 적합하지 않습니다.
Patrick Roberts

849

( 2016 년 업데이트 된 답변 참조 )

나는 행동을하고, 기다렸다가 다른 행동을하는 것이 타당하다고 생각합니다. 다중 스레드 언어로 작성하는 데 익숙하다면 스레드가 깨어날 때까지 일정 시간 동안 실행을 수행 할 수 있습니다.

여기서 문제는 JavaScript가 단일 스레드 이벤트 기반 모델이라는 것입니다. 특정한 경우 전체 엔진을 몇 초 동안 기다리게하는 것이 좋을 수 있습니다. 일반적으로 나쁜 습관입니다. 직접 작성하는 동안 함수를 사용하고 싶다고 가정 해보십시오. 내가 당신의 방법을 불렀을 때, 나의 방법은 모두 얼어 붙었습니다. JavaScript가 어떻게 든 함수의 실행 컨텍스트를 보존하고 어딘가에 저장 한 다음 다시 가져와 나중에 계속하면 절전 모드가 발생할 수 있지만 기본적으로 스레딩입니다.

따라서 다른 사람들이 제안한 내용에 거의 얽매이지 않습니다. 코드를 여러 기능으로 나누어야합니다.

그렇다면 귀하의 질문은 약간 잘못된 선택입니다. 원하는 방식으로 잠을 자거나 방법을 제안해서는 안됩니다.


45
이것은 정답이 아닙니다. Javascript에 절전 기능이 없으면 ECMAScript에 필요하지 않기 때문입니다. Javascript 디자인을 담당하는 기관에서 디자인을 선택합니다. Javascript 런타임이 다음 코드 행을 실행하기 전에 주어진 시간 동안 대기하도록 만들 수 있었지만 그렇지 않은 것으로 선택되었습니다.
Didier A.

5
수면은 실시간 정밀도가 아닌 JavaScript로 완벽하게 구현 될 수 있습니다. 결국 그것은 이벤트 기반 시스템입니다. 비동기 호출이 완료되면 이벤트가 트리거됩니다. 수면이 끝날 때까지 브라우저에 제어가 반환 된 후 sleep ()이 발행되고 호출 함수로 제어를 반환 할 때 동일한 것을 사용할 수없는 이유는 없습니다. 또한, 개발자가 시간을 갖지 않고 완전히 리팩토링하는 것 외에 다른 방법을 찾을 수 없을 정도로 개발자가 설계를 망치기 전에 특히 잠자는 것이 편리하다는 데 동의합니다.
Lawrence

이 아이디어를 따르는 Hypnotic을 사용해보십시오. coolwanglu.github.io/hypnotic/web/demo.html
Tezcat

4
자바 스크립트를 단일 스레드라고 부르는 것은 신화입니다. 기술적으로는 정확하지만 기능적으로는 다중 스레드 언어처럼 작동합니다. fork ()를 시뮬레이션하는 것은 쉬운 일이 아니며 yield ()를 실제로 구현할 수는 없지만 공유 메모리를 사용하여 잠금 / 세마포어를 사용하면 아주 가까워 질 수 있습니다. 일반적인 프로그래머에게는 멀티 스레드로 취급하는 것이 좋습니다. 기술적 이름은 언어 개발자에게만 해당됩니다.
Benubird

8
sleep()JS에서 불가능한 이유 에 동의 하며 대부분의 경우 더 좋은 방법이 있습니다. 그러나 나는 엔진이 모든 것을 디자인 결함으로 묶는 방식을 여전히 고려하고있다. sleep()엔진이 CPU를 방해하고 앱을 미치광이처럼 멈추지 않고 언어가 특정 스크립트, 페이지 또는 기능으로 제한 되는 기능을 가질 수있는 이유는 없습니다 . 2015 년이며으로 전체 웹 브라우저를 중단 할 수 없습니다 while(1). 우리는 그런 것들을 위해 플래시를 가지고 있습니다.
Beejor

660

JavaScript에서는 가능한 빨리 종료 할 수 있도록 모든 함수를 다시 작성합니다. 브라우저를 다시 제어하여 DOM을 변경할 수 있습니다.

함수 중간에 수면을 원할 때마다을 사용하도록 리팩토링했습니다 setTimeout().

편집하다

모든 언어 내에서 악명 높은 수면 또는 지연 기능이 많이 논의되고 있습니다. 어떤 사람들은 주어진 기능을 발생시키기 위해 항상 신호 나 콜백이 있어야한다고 말하고 어떤 사람들은 때때로 임의의 지연 순간이 유용하다고 주장 할 것입니다. 나는 그들 자신과 하나의 규칙이 결코이 산업의 어떤 것도 지시 할 수 없다고 말합니다.

JavaScript 기능으로 수면 기능 작성이 간단하고 더욱 유용합니다.

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

190
폐쇄 방식으로. function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
혼돈

68
웹 코드에서 코드를 사용하지 않으려면 어떻게해야합니까?
Eugenio Miró

10
@ EugenioMiró 코드가 웹 페이지에서 사용되도록 의도되지 않은 경우 호스트의 객체 모델이 휴면 방법을 구현하도록합니다. -질문은 웹 페이지에서 실행되는 자바 스크립트에 노출되는 DOM에 대한 것이라고 생각합니다.
BrainSlugs83

31
@Nosredna 예, 비동기 호출 방법을 이해합니다. 이것은 sleep ()에 도움이되지 않습니다. 전화를 특정 순서로하고 데이터를 특정 순서로 되돌리려 고합니다. 나는 for 루프에서 5 단계 깊이 있습니다. 실행을 차단하고 싶습니다. 진정한 수면 방법은 "브라우저 속도를 늦추지"않으며, 수면 시계는 브라우저 및 여전히 차단중인 동안 CPU 시간을 원하는 다른 스레드로 다시 제어합니다.
BrainSlugs83

382
이것은 질문에 대한 답변이 아닙니다.
TMS

303

debug / dev 만 누군가에게 유용하다면 이것을 게시합니다.

Firebug (및 아마도 다른 js 콘솔)에서 흥미로운 것들은 지정된 수면 시간 후에 만 ​​Enter 키를 누른 후에는 아무 일도 일어나지 않습니다 (...)

function sleepFor( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
}

사용 예 :

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }

36
이것은 답이 아닙니다. 약간 짧은 것을 제외하고는 문제의 코드와 정확히 동일합니다.
jab

16
바빠서 정말? JS에서? 몇 초? 이 작업을 수행하는 웹 사이트를 잡으면 차단됩니다.
mafu

34
@mafu 그것이 그렇게 말하는 이유입니다 only for debug/dev... rolleyes
xDaizu

11
절대이 작업을 수행하지 마십시오. 그러면 CPU가 실행하는 코어에서 CPU가 100 %에 도달하여 차단됩니다.
noego

3
async / await는 도움이되지 않기 때문에 명령 줄 자바 스크립트 응용 프로그램 내에서 유용하며, 아마도 유일한 잠자기 방법입니다.
Wheezil

177

나는 다른 포스터에 동의합니다. 바쁜 수면은 나쁜 생각입니다.

그러나 setTimeout은 실행을 보류하지 않으며 시간 종료가 만료 된 후가 아니라 시간 종료가 SET 직후에 다음 함수 행을 실행하므로 휴면과 동일한 태스크를 수행 할 수 없습니다.

이를 수행하는 방법은 부품을 부품 전후로 분류하는 것입니다.

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

함수 이름이 각 부분이 수행하는 작업을 정확하게 설명하는지 확인하십시오 (예 : funcPart1 및 funcPart2가 아닌 IE GatherInputThenWait 및 CheckInput).

편집하다

이 방법은 제한 시간이 지나면 결정한 코드 줄을 실행하지 않고 큐에 대기 한 다른 항목을 실행하기 위해 클라이언트 PC로 다시 제어를 되 돌리는 목적을 달성합니다.

추가 편집

주석에서 지적했듯이 이것은 루프에서 절대 작동하지 않습니다. 루프에서 작동하도록 멋진 (추악한) 해킹을 수행 할 수는 있지만 일반적으로 비참한 스파게티 코드를 만들 것입니다.


12
네. 까다로운 부분은 루프 또는 중첩 루프가있을 때입니다. for 루프를 포기하고 대신 카운터를 가져야합니다.
Nosredna 2016 년

터치 내 말은, 여전히 가능하지만 그 경우 추악하고 해킹 적입니다. 정적 부울 상태 변수를 사용할 수도 있지만 꽤 해킹 적입니다.
DevinB 2016 년

2
이를 위해 -1입니다. 다시, 이것은 질문에 대답하지 않습니다. 이것은 "코드 실행을 차단하는 방법"과는 매우 다른 "함수를 비동기 적으로 실행하는 방법"과 같은 질문에 대한 답입니다.
Deepak GM

6
@Nosredna 아니요, 폐쇄를 사용합니다. 예를 들면 다음 function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); }과 같습니다. and for(var X = 0; X < 3;X++) { foo(X); }- X 의 이로 전달되어 결국 호출 될 때 foo이름 아래에서 재사용됩니다 . indexfoo_continue
Izkata

2
@Alexander 물론 그렇습니다. setTimeout ()의 포인트는 코드를 비동기 적으로 실행하여 브라우저가 잠기는 것을 방지하기 때문입니다. console.log()내부 foo_continue()를 setTimeout 버전에 넣으면 동일한 결과를 얻습니다.
이즈 카타

132

$ DEITY를 사랑하기 위해 바쁘게 기다리는 수면 기능을 만들지 마십시오. setTimeout그리고 setInterval당신이 필요로하는 모든 것을 할.

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
    ;
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

2 초 간격마다 1 초 동안 텍스트가 숨겨집니다. setInterval 및 setTimeout을 사용하여 매초마다 텍스트를 표시하고 숨기는 방법을 보여줍니다.


3
다는 아니지만 setInterval은 폴링에 대해 훨씬 더 나은 인상을줍니다.
annakata 2016 년

3
그 코드 조각이 JavaScript 엔진에서 무엇을 지지하지 않습니까?
Deniz Dogan 2016 년

10
수면을 동기식으로 유지해야하는 경우가 아니면 완전히 유효한 질문입니다.
Aaron Dufour

36
우리 중 많은 사람들이 JavaScript가 브라우저 전용 언어가 아니라는 사실을 잊고있을 수도 있습니다. 이 친구는 setTimeout과 함께 제공되는 모든 변수 범위 지정 문제를 처리 할 필요없이 잠시 일시 중지해야하는 노드 명령 행 유틸리티를 작성 중일 수 있습니다.
Phil LaNasa

3
@PhilLaNasa : 구문 적 폐쇄가 여전히 겁나면 노드 101을 심각하게 중단하고 작동시켜야합니다.
혼돈

113

나는 이것이 오래된 질문이라는 것을 알고 있지만 (나 같은) Rhino와 함께 Javascript를 사용하고 있다면 사용할 수 있습니다 ...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}

4
이것이 Java에 대한 호출입니까?
Ken Sharp

14
이것은 자바가 아닌 자바이다
RousseauAlexandre

18
@RousseauAlexandre 잘못되었습니다. 그것은는 자바 스크립트 (시, 그것은 동등하게 Nashorn에게 이러한 일이 될 수 있음) 코뿔소를 사용하여
mjaggard

71

jQuery를 사용하는 경우 누군가가 실제로 setTimeout에 대한 랩퍼 인 "지연"플러그인을 작성했습니다.

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

그런 다음 예상대로 함수 호출 행에서 사용할 수 있습니다.

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

4
그것은 나쁜 해결책이 아닙니다. 맥락과 연쇄 성을 유지합니다.
Nosredna 2016 년

39
jQuery 1.4 .delay()부터는 jQuery의 일부입니다 (위 구현과 다른 의미론을 가지고 있음). api.jquery.com/delay
매트 볼

7
이 질문에 분명히 부족한 것은 jQuery 답변 이었습니다. 너무 기뻐요!
xDaizu

1
두 개의 독립 통화 사이에 지연이 필요한 경우 가능합니다. 루프 속도를 늦추기 위해 지연이 필요한 경우 아닙니다.
WGroleau

46

수면 솔루션도 검색했습니다 (생산 코드가 아닌 개발자 / 테스트 전용).이 기사를 찾았습니다.

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

... 그리고 여기에는 클라이언트 측 솔루션과의 또 다른 링크가 있습니다 : http://www.devcheater.com/

또한을 호출 할 때 alert()경고가 표시되는 동안 코드도 일시 중지됩니다. 경고를 표시하지 않지만 동일한 효과를 얻는 방법을 찾아야합니다. :)


35
많은 사람들이 "아니오, 프로덕션 코드에서는이 작업을 수행하지 마십시오!"라고 말합니다. 그래, 난 싫어 나는 끔찍한 테스트 코드로하고 싶기 때문에 우아한 솔루션을 만드는 데 많은 시간을 소비하고 싶지 않습니다.
user435779

31

다음은 동기 XMLHttpRequest를 사용하는 간단한 솔루션입니다.

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

sleep.php의 내용 :

<?php sleep($_GET['n']);

이제 다음과 같이 호출하십시오. sleep (5);


5
@lukad, setTimeout()작동하는 경우 사용 하지만 콜백 1000 줄을 풀면 농담처럼 보이지 않을 수 있습니다.
pguardiario

11
불행히도 비동기가 아닌 XMLHttpRequests는 더 이상 사용되지 않으며 향후 제거 될 예정입니다. 그 사실이 처음 에이 질문으로 이끌었 기 때문에 어느 것이 재미 있습니다.
Beejor

이것은 실제로 좋은 아이디어 IMO입니다. 수면 API (요청 URL)가 남용 될 수 있으므로 공개되어야한다고 생각하지는 않습니다.
Vahid Amiri

@Beejor는 항상 미래에 대해서만 생각하는 것은 미래의 비현실에 살고 있음을 의미합니다. :-)
user1742529

좋았지 만 언젠가 인터넷이 느리거나 웹 사이트 핑 시간이 논쟁 시간보다 스크립트를 잠들게하는 것보다 높은지 알고 있습니까 sleep(300)자바 스크립트 코드보다 450ms 동안 대기하는 것보다 웹 사이트 를 사용 하고 응답하는 데 150ms의 시간이 걸리는 것처럼 . 브라우저에서 인터넷 연결이 끊어지면 0ms 동안 만 작동합니다. 따라서 더 나은 솔루션은 아닙니다
H Chauhan

30

여기 요 코드에서 알 수 있듯이 나쁜 개발자가 아니며 웹 사이트에서 사용하십시오. 개발 유틸리티 기능입니다.

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}

17
기본적으로 OP와 동일합니다.
앤드류 이발사

5
더 정확하게 말하면 OP가 대안을 요구 한 것입니다.
WGroleau

해결책은 좋지 않지만 일부 지역 async/await에서는 불행히도 응답하지 않으므로 우리는 그것을 직접 사용해야합니다.
Nabi KAZ

21

나는 개인적으로 간단한 것을 좋아한다.

function sleep(seconds){
    var waitUntil = new Date().getTime() + seconds*1000;
    while(new Date().getTime() < waitUntil) true;
}

그때:

sleep(2); // Sleeps for 2 seconds

P5js에서 스크립트를 만드는 동안 가짜로드 시간을 만들기 위해 항상 사용하고 있습니다.


3
나는 이것을 주요 질문의 가장 최적화 된 버전으로 본다 : 그것은 루프 내에서 수학을 수행하지 않고 평범한 비교입니다. 읽기가 조금 어렵습니다.
hegez

4
절대 그렇게하지 마십시오. 이 기능이 작동하는 동안 CPU 사용량을 확인 했습니까? 충분한 시간을 주면 100 %에 가까워 야합니다.
noego

2
@ hegez : 루프가 고정 된 양의 벽시계 시간 동안 실행될 것이라는 점을 감안할 때 루프를 최적화하는 것이 포인트 옆에있는 것처럼 보입니다.
ShadowRanger

@noego 어떻게 그렇게? 방금 노드 10에서 테스트 한 결과 CPU 사용량이 전혀 변경되지 않았습니다.
melMass

@melMass이 함수는 CPU를 100 % 사용 상태로 유지하여 n 초 동안 노드 스레드를 차단합니다. 이 "솔루션"은 이러한 두 가지 이유 (블로킹 + CPU 킬러)에 대한 매우 나쁜 아이디어입니다. HAS가 블로킹되지 않도록 대기 중이므로 비동기식입니다.
제레미 틸

20

먼저:

다음과 같이 실행하려는 함수를 정의하십시오.

function alertWorld(){
  alert("Hello World");
}

그런 다음 setTimeout 메소드를 사용하여 실행을 스케줄하십시오.

setTimeout(alertWorld,1000)

두 가지 참고

  • 두 번째 논쟁은 밀리 초 단위의 시간입니다
  • 첫 번째 인수로 괄호없이 함수의 이름 (참조) 만 전달하면됩니다.

18

대부분의 사람들이 원하는 것처럼 보이게하는 더 나은 솔루션은 익명 함수를 사용하는 것입니다.

alert('start');
var a = 'foo';
//lots of code
setTimeout(function(){  //Beginning of code that should run AFTER the timeout
    alert(a);
    //lots more code
},5000);  // put the timeout here

이것은 아마도 당신이 원하는 것을 단순히 수행하는 것에 가장 가까운 것입니다.

여러 번 수면이 필요한 경우 서두르면 추악해질 수 있으며 실제로 디자인을 다시 생각해야 할 수도 있습니다.


이것은 데스크탑 브라우저 및 구형 휴대 전화에서 나를 위해 일한 것입니다. 내가 시도한 다른 사람들은 전혀 작동하지 않았습니다.
Mike


10

브라우저의 경우 setTimeout 및 setInterval이 갈 길에 동의합니다.

그러나 서버 측 코드의 경우 차단 기능이 필요할 수 있습니다 (예 : 스레드 동기화를 효과적으로 수행 할 수 있음).

node.js 및 meteor를 사용하는 경우 광섬유에서 setTimeout을 사용하는 데 한계가있을 수 있습니다. 다음은 서버 측 절전 코드입니다.

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

참조 : https://github.com/laverdet/node-fibers#sleep


Server may require a blocking function... 나는 어떻게 강제로 노드의 유일한 스레드를 차단보고 몇 초 동안 전체 서버 응답이 좋은 아이디어인지 확인하지 않지만 어떤
제레미 Thille

10

다른 비동기 작업과 코드 일관성을 유지하기 위해 Promise에 setTimeOut을 캡슐화합니다. Demo in Fiddle

function sleep(ms)
{
    return(new Promise(function(resolve, reject) {        
        setTimeout(function() { resolve(); }, ms);        
    }));    
}

그런 식으로 사용 :

sleep(2000).then(function() { 
   // Do something
});

약속을 사용했던 경우 구문을 기억하기 쉽습니다.


4
왜 setTimeout (function () {/ * do something * /}, 2000);을 사용하는 것보다 더 좋은 이유는 무엇입니까?
JSideris

10

Atomics.wait를 사용한 2019 업데이트

노드 9.3 이상에서 작동해야합니다.

Node.js에서 꽤 정확한 타이머가 필요했으며 그 기능이 훌륭합니다. 그러나 브라우저에서 지원이 극히 제한적인 것 같습니다.

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

몇 10 초 타이머 벤치 마크를 실행했습니다.

setTimeout을 사용하면 최대 7000 마이크로 초의 오류가 발생합니다. (7ms)

Atomics에서 내 오류는 600 마이크로 초 미만으로 유지됩니다. (0.6ms)

2020 업데이트 : 요약

function sleep(millis){ // need help of a server-side page
  let netMillis=Math.max(millis-5,0); //assuming 5ms overhead
  let xhr=new XMLHttpRequest();
  xhr.open('GET','/sleep.jsp?millis='+netMillis+'&rand='+Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}
function sleepAsync(millis){ // use only in async function
  let netMillis=Math.max(millis-1,0); // assuming 1ms overhead
  return new Promise((resolve)=>{
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}
async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}
function sleepSyncTest(){ 
  let source=`${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src='data:text/javascript,'+encodeURIComponent(source);
  console.log(src);
  var worker=new Worker(src);
}

서버 쪽 페이지 sleep.jsp는 다음과 같습니다.

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>

내 의견으로는 호출자에서 async / await없이 간단한 함수로 구현 할 수없는 허용 된 솔루션보다 낫습니다.
GroovyDotCom

네, 이것이
막히고

꽤 멋지지만 이것이 실제로 Chrome 및 Firefox 에서만 지원된다는 사실 은 웹에서 사용하기에 적합하지 않습니다. (2019 년 11 월)
JGreatorex 2018

9

여기에있는 대부분의 답변은 잘못 안내되거나 최소한 구식입니다. 자바 스크립트가 단일 스레드 여야하는 이유는 없으며 실제로는 그렇지 않습니다. Rhino 및 Node.js와 같은 다른 자바 스크립트 런타임이 멀티 스레딩을 지원하기 전에 오늘날 모든 주류 브라우저는 작업자를 지원합니다.

'자바 스크립트는 단일 스레드입니다'는 올바른 답변이 아닙니다. 예를 들어 작업자 내에서 절전 기능을 실행하면 ui 스레드에서 실행되는 코드가 차단되지 않습니다.

생성기와 수율을 지원하는 최신 런타임에서는 단일 스레드 환경에서 유사한 기능을 휴면 기능에 제공 할 수 있습니다.

// This is based on the latest ES6 drafts.
// js 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// run code you want to sleep here (ommit star if using js 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // to sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // ommit .value if using js 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// initialize generator and get first sleep for recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// initialize recursive resume function
resume(firstSleep, generator);

이 수면 모방은 스레드를 차단하지 않으므로 실제 수면 기능과 다릅니다. Javascript의 현재 setTimeout 함수 위에 설탕입니다. 이 기능 유형은 Task.js 에서 구현되었으며 오늘날 Firefox에서 작동합니다.


작업자는 적어도 버전 10을 통해 IE에서 구현되지 않습니다. 현재 많은 사용자를 나타냅니다.
Beejor

물론 sleep여러 작업자를 사용하여 구현 하는 것은 실용적이지 않습니다 . Node.js 생성기를 사용하면 함수가 이미 구현되어 있으며 설명대로 사용할 수 있습니다. 주류 브라우저는 오늘날 모든 생성기를 구현하지 않았습니다.
Gabriel Ratener

8

javascript sleep / wait에서 꽤 많은 웹 페이지를 검색 / 검색했으며 ... Javascript를 "RUN, DELAY, RUN"으로 설정하려는 경우 대답이 없습니다 ... 대부분의 사람들이 얻은 것은 "RUN, RUN (무용 지) stuff), RUN "또는"RUN, RUN + delayed RUN "....

그래서 나는 햄버거를 먹었고 생각했습니다. 아직도 ...

// ......................................... // example1 :

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setInterval
var i = 0;

function run() {
    //pieces of codes to run
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next...
}

run();
t=setInterval("run()",1000);

</script>
</body>
</html>

// .................................... // example2 :

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function run() {
    //pieces of codes to run, can use switch statement
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(1000);}
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(2000);}
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(3000);}
    if (i==3){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()",dur);} //starts flow control again after dur

run(); //starts
</script>
</body>
</html>

// ................. 예 3 :

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow
</script>
</body>
</html>

// .............. example4 :

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); //stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    i++; //current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow control for first time...
</script>
</body>
</html>

5
좋아, 이것은 setTimeput과 함께 작동하지만 무슨 일이 일어나고 있는지 알기가 어렵습니다. setTimeout 자체를 사용하는 것이 이보다 쉽습니다.
naugtur

7
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

실제 질문과 동일합니다. 그것을 진정한 답으로 만드는 것은별로 중요하지 않습니다.
EML

2
좋은 해결책은 아닙니다-Selenium의 JavaScriptExecutor에서 이것을 사용하면 Chrome 브라우저가 2104 MacBook Pro의 시간의 약 50 %를 중단합니다.
emery

7

의존성이없는 가장 짧은 솔루션 :

await new Promise(resolve => setTimeout(resolve, 5000));

IE11에서는 작동하지 않습니다. 화살표 함수에 대한 구문 오류가 발생합니다.
DDphp

@ Java-DK 사용await new Promise(function(resolve) { setTimeout(resolve, 5000); });
k06a

6

당신은 JavaScript에서 그런 식으로 잠을 잘 수 없거나 오히려해서는 안됩니다. 휴면 또는 while 루프를 실행하면 루프가 완료 될 때까지 사용자 브라우저가 정지됩니다.

참조한 링크에 지정된대로 타이머를 사용하십시오.


6

setTimeout ()을 사용하지 않고 sleep () 함수를 원할 수있는 한 가지 시나리오는 사용자 클릭에 응답하는 함수가 궁극적으로 새 ie 팝업 창을 열고 짧은 기간이 필요한 처리를 시작한 경우입니다. 팝업이 표시되기 전에 완료하십시오. 열린 창을 클로저로 이동하면 일반적으로 브라우저에 의해 차단됩니다.


6

동기 실행을 처리 해야하는 경우 절전 기능의 목적을 이해할 수 있습니다. setInterval 및 setTimeout 함수는 실행 순서를 기본 프로그램으로 다시 리턴하는 병렬 실행 스레드를 작성하므로 지정된 결과를 기다려야하는 경우에는 효과가 없습니다. 물론 이벤트와 핸들러를 사용할 수도 있지만 경우에 따라 의도하지 않은 경우도 있습니다.


6

내 두 비트를 추가합니다. 테스트 목적으로 바쁜 대기가 필요했습니다. 많은 작업이 될 것이므로 코드를 나누고 싶지 않았기 때문에 간단한 작업이었습니다.

for (var i=0;i<1000000;i++){                    
     //waiting
  }

나는 이것을하는 데 어떤 단점도 보지 못했고 그것은 나를 위해 속임수를했다.


그것은 컴파일 될 수 있습니다.
Viktor Sehr

이런 식으로하지 마십시오. 이것은 차단 휴면 호출이므로 코드가 JS 스레드를 호그하는 동안 다른 자바 스크립트를 실행할 수 없습니다.
Steve Midgley

5
@SteveMidgley "코드에서 JS 스레드를 실행하는 동안 실행할 수있는 다른 자바 스크립트가 없습니다"는 OP가 원하는 것이 바로 ¯_ (ツ) _ / ¯
drigoangelo

1
방금 몇 가지 테스트를 실행했으며 빈 루프조차도 브라우저와 CPU (JavaScript뿐만 아니라)를 차단합니다. 그리고 for루프를 사용 하면의 최대 값과 상관없이 거의 항상 즉시 실행 i되며 복잡한 수학 코드가 내부에도 배치됩니다. 따라서 몇 밀리 초만 기다리지 않으면 JS에서 정상적으로 잠자는 방법이없는 것 같습니다.
Beejor

백만이 너무 큽니다. 나를 위해 충분히 10k
Vlad

6

Java의 휴면 방법을 사용하여 수행 할 수 있습니다. 나는 FF와 IE에서 테스트했으며 컴퓨터를 잠 그거나 리소스를 씹거나 끝없는 서버 히트를 유발하지 않습니다. 나에게 깨끗한 해결책 인 것 같습니다.

먼저 페이지에 Java를로드하고 해당 메소드를 사용 가능하게해야합니다. 그렇게하기 위해 나는 이것을했다 :

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

그런 다음 JS에서 고통없이 일시 중지를 원할 때해야 할 일은 다음과 같습니다.

java.lang.Thread.sleep(xxx)

여기서 xxx는 시간 (밀리 초)입니다. 필자의 경우 (정당하게) 매우 작은 회사에서 백엔드 주문 이행의 일부였으며 서버에서로드해야하는 송장을 인쇄해야했습니다. 송장을 (웹 페이지로) iFrame에로드 한 다음 iFrame을 인쇄하여 수행했습니다. 물론 인쇄하기 전에 페이지가 완전히로드 될 때까지 기다려야하므로 JS를 일시 중지해야했습니다. 인보이스 페이지 (iFrame)가 onLoad 이벤트를 사용하여 부모 페이지의 숨겨진 양식 필드를 변경하도록하여이를 수행했습니다. 그리고 인보이스를 인쇄하는 상위 페이지의 코드는 다음과 같습니다 (명확성을 위해 관련 부분이 잘리지 않음).

var isReady = eval('document.batchForm.ready');
isReady.value=0;

frames['rpc_frame'].location.href=url;

while (isReady.value==0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

따라서 사용자가 버튼을 누르면 스크립트가 송장 페이지를로드 한 다음 대기하며, 1 초마다 확인하여 송장 페이지로드가 완료되었는지 확인한 다음 사용자가 인쇄 대화 상자를 프린터로 보낼 수 있도록합니다. QED.


12
저자가 달성하고자하는 단순한 것을 고려할 때 상당히 괴물 같은 것 같습니다.
xaralis

2
이것은 더 이상 사용되지 않는 Java 애플릿에 따라 다릅니다.
Vahid Amiri

6

많은 답변이 (직접적으로) 질문에 대답하지 않으며, 어느 것도 대답하지 않습니다 ...

내 두 센트 (또는 기능)는 다음과 같습니다.

setTimeoutand 보다 덜 교묘 한 함수를 원한다면 setInterval인수의 순서를 반대로 바꾸어 멋진 이름을 지정하는 함수로 묶을 수 있습니다.

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScript 버전 :

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

그런 다음 익명 함수로 잘 사용할 수 있습니다.

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

이제는 "N 밀리 초 후에 ..."(또는 "N 밀리 초마다 ...")로 쉽게 읽 힙니다.


5

루프에 의해 실행되는 일련의 호출을 분리하려는 특정 경우 프로토 타입에 아래 코드와 같은 것을 사용할 수 있습니다. 프로토 타입이 없으면 지연 기능을 setTimeout으로 대체 할 수 있습니다.

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}

5

node.js를 사용하는 경우 섬유를 살펴볼 수 있습니다 하는 경우 일종의 다중 스레딩 시뮬레이션 인 대한 기본 C 확장 인 .

sleep광섬유에서 실행을 차단하는 방식으로 실제 작업을 수행 할 수 있지만 주 스레드 및 기타 광섬유에서는 차단되지 않습니다.

다음은 자신의 readme에서 새로 만든 예입니다.

// sleep.js

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

– 결과는 다음과 같습니다.

$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.