JavaScript에서 잠자기-동작 간 지연


129

JavaScript에서 다른 작업을 수행하기 전에 잠을 잘 수있는 방법이 있습니까?

예:

 var a = 1+3;
 // Sleep 3 seconds before the next action here
 var b = a + 4;

답변:


140

setTimeout비슷한 효과를 얻는 데 사용할 수 있습니다 .

var a = 1 + 3;
var b;
setTimeout(function() {
    b = a + 4;
}, (3 * 1000));

이것은 실제로 JavaScript를 '슬립'하는 것이 아니라 setTimeout특정 지속 시간 (밀리 초로 지정) 후에 전달 된 함수를 실행하기 만합니다. JavaScript에 대해 절전 기능을 작성할 수는 있지만 setTimeout수면 기간 동안 모든 항목이 고정되지 않기 때문에 가능한 경우 사용 하는 것이 가장 좋습니다 .


9
setInterval ()도 살펴보십시오. setTimeout ()과 비슷하지만 함수는 여러 번 호출됩니다 (중지 될 때까지). 수면 중에 작업 진행 (업데이트 업데이트 수행, 내부 상태 유지 등)을 수행하려는 경우에 유용합니다.
Anders Sandvig

5
이것은 질문에 대답하지 않습니다. 이 질문은 그렇지 않은 "수면"에 해당한다.
felwithe

이 답변은 질문과 일치하지 않지만 루프보다 유용하고 Date.now ()를 비교하십시오. 블록 루프를 사용하는 사람은 기계를 잠들지 않습니다.
Li Chunlin

2
물론, 차단 루프가,하지 않는 한 정확히 누군가가 원하는 것을.
Sane Wonko

55

실제로 sleep()무언가를 테스트하기 위해 꼭 필요한 경우가 있습니다 . 그러나 디버그하는 동안 브라우저가 대부분 충돌하는 경우가 있으므로 어쨌든 필요할 수 있습니다. 프로덕션 모드에서는이 기능에 대해 언급하겠습니다.

function pauseBrowser(millis) {
    var date = Date.now();
    var curDate = null;
    do {
        curDate = Date.now();
    } while (curDate-date < millis);
}

new Date()메모리, 처리 능력, 배터리 및 장치 수명을 낭비하지 않으려면 루프에서 사용하지 마십시오 .


8
이 답변에는 더 많은 투표가 필요합니다. 질문에 출연하면이 답변의 원인이됩니다.
jagc

"너무 많은 재귀"경고는 어떻습니까?
Oki Erie Rinaldi 4

1
@OkiErieRinaldi 거기에는 재귀가 없으며 루프 일뿐입니다.
로드리고

7
글쎄, 누군가 "잠자기"기능을 요청했습니다. 그것이 바로 여기에 있습니다. 한 번 사용했는데 어떤 종류의 디버깅을 정확하게 기억할 수 없습니다. 다시 필요할 경우 정확히 어디서 찾을 수 있는지 알고 있습니다. 다른 기능을 선호한다면 그게 당신의 선택입니다. 선택할 수있는 것이 좋지 않습니까?
로드리고

2
"바쁨 대기".
Zeek2

13

ECMAScript 6 버전, "코드 블로킹"을위한 생성기를 사용한 생성기 :

원래 질문은 7 년 전에 게시되었으므로 너무 간단하고 이미 답변 되었기 때문에 정확한 코드로 대답하지 않았습니다. 이는 최소 두 개의 휴면이 필요하거나 비동기 실행을 시퀀싱하려는 경우와 같이보다 복잡한 문제에 도움이됩니다. 필요에 따라 자유롭게 수정하십시오.

let sleeptime = 100
function* clock()
{
    let i = 0
    while( i <= 10000 )
    {
        i++
        console.log(i); // actually, just do stuff you wanna do.
        setTimeout(
            ()=>
            {
                clk.next()
            }
            , sleeptime
        )
        yield
    }
}

let clk = clock()
clk.next()

함수*

() => 화살표 기능

약속을 통해 이벤트를 연결할 수도 있습니다 .

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


sleep(1000).then(function()
{
    console.log('1')
    sleep(1000).then(function()
    {
        console.log('2')
    })
})

또는 훨씬 간단하고 덜 멋진 방법은

function sleep(ms, f)
{
    return(
        setTimeout(f, ms)
    )
}


sleep(500, function()
{
    console.log('1')
    sleep(500, function()
    {
        console.log('2')
    })
})
console.log('Event chain launched')

어떤 상황이 발생하기를 기다리는 경우 다음과 같이 기다릴 수 있습니다

function waitTill(condition, thenDo)
{
    if (eval(condition))
    {
        thenDo()
        return
    }

    setTimeout(
        ()    =>
        {
            waitTill(condition, thenDo)
        }
        ,
        1
    )
}

x=0

waitTill(
    'x>2 || x==1'
    ,
    ()    =>
    {
        console.log("Conditions met!")
    }
)

// Simulating the change
setTimeout(
    () =>
    {
        x = 1
    }
    ,
    1000
)


11

2018 업데이트

최신 Safari, Firefox 및 Node.js도 이제 async / await / promises를 지원합니다.

async / await / Promises 사용 :

(2017 년 1 월 현재, Chrome에서는 지원되지만 Safari, Internet Explorer, Firefox, Node.js에서는 지원되지 않음)

'use strict';

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

let myAsyncFunc = async function() {
  console.log('Sleeping');
  await sleep(3000);
  console.log('Done');
}

myAsyncFunc();

2017 년 업데이트

이 질문이 제기 된 이후 JavaScript가 발전했으며 이제 생성기 기능이 있으며 새로운 async / await / Promise가 출시되고 있습니다. 아래에는 두 가지 솔루션이 있습니다. 하나는 모든 최신 브라우저에서 작동하는 생성기 기능과 다른 곳에서는 아직 지원되지 않는 새로운 async / await를 사용합니다.

생성기 기능 사용 :

'use strict';

let myAsync = (g) => (...args) => {
    let f, res = () => f.next(),
        sleep = (ms) => setTimeout(res, ms);
    f = g.apply({sleep}, args); f.next();
};

let myAsyncFunc = myAsync(function*() {
    let {sleep} = this;
    console.log("Sleeping");
    yield sleep(3000);
    console.log("Done");
});

myAsyncFunc();

이 두 솔루션이 모두 비동기식이라는 사실에주의하십시오. 이는 myAsyncFunc (두 경우 모두)가 절전 모드에서 돌아 오는 것을 의미합니다.

이 질문은 JavaScript 버전 인 sleep ()과 다른 점에 유의해야합니다 . 요청자가 조치 사이의 지연이 아닌 실제 휴면 (프로세스에서 다른 코드 실행 없음)을 요청하는 경우.


1
지금까지 최고의 답변! 나는 그것을 발견하기 위해 사방을 검색 30 분 보냈다 .. 큰 thx !!!
538ROMEO

1
나는 해결책을 찾고있는 동안이 대답을 놓치고 자전거를 다시 발명했습니다 : D 전에 그것을 보았을 경우 시간을 절약 할 수 있습니다!! 공감!
sserzant

let co = gen => (...args) => { let iter = gen(...args); let resume = () => new Promise((resolve, reject) => { let result = iter.next(); if (result.done) resolve(result.value); else Promise.resolve(result.value).then(resume).then(resolve, reject); }); return resume(); };두 번째 코드 블록에서 let asyncAdd = co(function* (a, b) { console.log('Sleeping'); yield sleep(3000); console.log('Done'); return a + b; }); asyncAdd(3, 4).then(console.log);정의를 사용 하도록 할 수 있습니다 sleep().
Patrick Roberts

3

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 밀리 초마다 ...")로 쉽게 읽 힙니다.


2

이를 수행하는 또 다른 방법은 Promise 및 setTimeout을 사용하는 것입니다 (함수 내에 있어야하며 async 키워드와 비동기로 설정해야 함).

async yourAsynchronousFunction () {

    var a = 1+3;

    await new Promise( (resolve) => {
        setTimeout( () => { resolve(); }, 3000);
    }

    var b = a + 4;

}

2

다음은 동기 절전 / 일시 정지와 같은 느낌을 갖지만 합법적 인 js 비동기 코드 인 매우 간단한 방법입니다.

// Create a simple pause function
const pause = (timeoutMsec) => new Promise(resolve => setTimeout(resolve,timeoutMsec))

async function main () {
    console.log('starting');
    // Call with await to pause.  Note that the main function is declared asyc
    await pause(3*1000)
    console.log('done');
}


1

일반 자바 스크립트를 사용할 수 있습니다. 5 초 후에 함수 / 메소드가 호출됩니다.

setTimeout(()=> { your_function(); }, 5000);

0

이 문제를 해결하는 방법에는 여러 가지가 있습니다. setTimeout함수 를 사용하면 먼저 알아 보자. 이 함수 에는 세 개의 매개 변수가 있습니다 : function또는 code, delay(밀리 초) 및 parameters. 때문에 기능 이나 코드 매개 변수가 필요하며, 나머지는 선택 사항입니다. 지연 시간을 입력하지 않으면 지연 시간 이 0으로 설정됩니다.

setTimeout() 이 링크로 이동 에 대한 자세한 내용은 .

간체 버전 :

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(function(){ 
    b = a + 4; 
    console.log('b = ' + b);
}, 1000);

출력 :
a = 4
24-> 활성 시간 초과 목록의 번호 식별자
b = 8


파라미터 패스 사용하기 :

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(myFunction, 1000, a);

function myFunction(a)
{
    var b = a + 4;
    console.log('b = ' + b);
}

출력 :
a = 4
25-> 활성 시간 초과 목록의 번호 식별자
b = 8



브라우저 지원 :

Chrome Firefox Edge Safari Opera
1.0 1.0 4.0 1.0 4.0

0

생성기 함수 (ES6)를 사용하여 자바 스크립트에서 "sleep"또는 "DoEvents"하는 방법을 보여주는 모델입니다. 주석이 달린 코드 :

<html>
<head>
<script>
  "use strict"; // always
  // Based on post by www-0av-Com /programming/3143928
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
  var divelt, time0, globaln = 0; // global variables
  var MainGenObj = Main(); // generator object = generator function()
window.onload = function() {
  divelt = document.getElementsByTagName("body")[0]; // for addline()
  addline("typeof Main: " + typeof Main);
  addline("typeof MainDriver: " + typeof MainDriver);
  addline("typeof MainGenObj: " + typeof MainGenObj);
  time0 = new Date().valueOf(); // starting time ms
  MainDriver(); // do all parts of Main()
}
function* Main() { // this is "Main" -- generator function -- code goes here
  // could be loops, or inline, like this:

  addline("Part A, time: " + time() + ", " + ++globaln); // part A
  yield 2000;                    // yield for 2000 ms (like sleep)

  addline("Part B, time: " + time() + ", " +  ++globaln); // part B
  yield 3000;                    // yield for 3000 ms (or like DoEvents)

  addline("Part Z, time: " + time() + ", " +  ++globaln); // part Z (last part)
  addline("End, time: " + time());
}
function MainDriver() { // this does all parts, with delays
  var obj = MainGenObj.next(); // executes the next (or first) part of Main()
  if (obj.done == false) { // if "yield"ed, this will be false
    setTimeout(MainDriver, obj.value); // repeat after delay
  }
}
function time() { // seconds from time0 to 3 decimal places
  var ret = ((new Date().valueOf() - time0)/1000).toString();
  if (ret.indexOf(".") == -1) ret += ".000";
  while (ret.indexOf(".") >= ret.length-3) ret += "0";
  return ret;
}
function addline(what) { // output
  divelt.innerHTML += "<br />\n" + what;
}
</script>
</head>
<body>
<button onclick="alert('I\'m alive!');"> Hit me to see if I'm alive </button>
</body>
</html>

0

이 기능을 사용해보십시오 :

const delay = (ms, cb) => setTimeout(cb, ms)

사용 방법은 다음과 같습니다.

console.log("Waiting for 5 seconds.")
delay(5000, function() {
  console.log("Finished waiting for 5 seconds.")
})

또는 약속 스타일로 이동하십시오.

const delay = ms => new Promise(resolve => {
    setTimeout(resolve, ms)
})

여기 데모가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.