Node.js (자바 스크립트)에서 어떻게 기다릴 수 있습니까?


385

개인의 요구에 맞는 스크립트와 같은 콘솔을 개발 중입니다. 오랜 시간 동안 일시 중지 할 수 있어야하지만 내 연구에서 node.js는 필요에 따라 중지 할 수 없습니다. 일정 기간이 지나면 사용자 정보를 읽기가 어려워지고 있습니다 ... 코드가 몇 개 있지만, 내부에 다른 코드가 있어야 다음과 같은 작업을 수행 할 수 있습니다.

setTimeout(function() {
}, 3000);

그러나 일정 기간이 지나면이 코드 줄 뒤의 모든 것이 실행되어야합니다.

예를 들어

//start-of-code
console.log('Welcome to My Console,');
some-wait-code-here-for-ten-seconds..........
console.log('Blah blah blah blah extra-blah');
//endcode. 

나는 또한 같은 것들을 보았다

yield sleep(2000);

그러나 node.js는 이것을 인식하지 못합니다.

이 연장 된 일시 정지를 어떻게 달성 할 수 있습니까?


3
이 사람들 중 하나를 정답으로 표시하는 방법 :)
Billybonks

1
@Christopher Allen, 아마도 관련이 없지만 일을합니다 : require("child_process").execSync('php -r "sleep($argv[1]);" ' + seconds);
Haitham Sweilem

노드 슬립 트릭을 할 수있는 NPM 모듈 (그러나, 나는 단지 디버깅을 위해 사용할 것)
줄리안 소로

답변:


211

이를 수행하는 가장 좋은 방법은 다음과 같이 코드를 여러 함수로 나누는 것입니다.

function function1() {
    // stuff you want to happen right away
    console.log('Welcome to My Console,');
}

function function2() {
    // all the stuff you want to happen after that pause
    console.log('Blah blah blah blah extra-blah');
}

// call the first chunk of code right away
function1();

// call the rest of the code and have it execute after 3 seconds
setTimeout(function2, 3000);

JohnnyHK 의 솔루션 과 비슷 하지만 훨씬 깔끔하고 확장하기 쉽습니다.


7
@LucasSeveryn 그렇다면 뭔가 잘못하고 있습니다. 이것이 핵심 디자인 패턴입니다.
Elliot Bonneville 2016 년

그리고 함수의 시작이 단지 하나의 함수가 아니라 비 동기화되어야하는 코드에서 10 개의 파일이 떨어져있을 때 무엇을합니까?
Cyril Duchon-Doris

10
@ CyrilDuchon-Doris 무엇?
AturSams

3
사용 @ machineghost의 답변을 사용자 지정 코드 및 지원 더 필요하지 않은 우아한 약속을 기반으로 솔루션을 await를 / 비동기
덴마크 맥컬리

이것은 비동기입니다. 이는 function1이 3 초 전에 종료되면 서로 겹치기 시작 함을 의미합니다. 그러면 돌아올 수 없으며 거의 ​​활용할 수 없습니다. 내가 지금까지 찾은 유일한 방법은debugger;
Cristian Traìna

427

오래된 질문에 대한 새로운 답변. 오늘 ( 2017 년 1 월 6 월 2019) 훨씬 쉽습니다. 새로운 async/await구문을 사용할 수 있습니다 . 예를 들면 다음과 같습니다.

async function init() {
  console.log(1);
  await sleep(1000);
  console.log(2);
}

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

사용하기 위해 async/await설치 및 플러그인없이 상자 밖으로, 당신은 사용하여 노드-V7 또는 노드-V8을 사용할 필요가 --harmony플래그를.

2019 년 6 월 업데이트 : 최신 버전의 NodeJS를 사용하면 즉시 사용할 수 있습니다. 명령 줄 인수를 제공 할 필요가 없습니다. 오늘날에도 Chrome에서도 지원합니다.

2020 년 5 월 업데이트 :await비동기 함수 외부 에서 구문 을 사용할 수 있습니다. 이 예와 같이 최상위 수준에서

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

제안은 3 단계에 있습니다. webpack 5 (알파)를 사용하여 오늘 사용할 수 있습니다.

더 많은 정보:


5
나는 당신 await이 앞에 키워드 를 잊어 버린 것 같아요sleep(1000)
Ryan Jarvis

6
이것은 실제로 답이되어야합니다 .sleep node.js 패키지는 번거로울 수 있습니다.
스튜어트 앨런

4
실제로 최고의 솔루션
Kostas Siabanis

40
let sleep = ms => new Promise(resolve => setTimeout(resolve, ms));: 자신과 같은 oneliner 괴물을 위해
프레드 락 Stojadinović

21
let sleep = require('util').promisify(setTimeout);노드 7.6+에 작품과 개선 가독성
BrianHVB

216

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

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

14
"정교함의 높이는 단순합니다." -클레어 부스 루체 이것이 가장 좋은 답입니다. IMO.
arnold

3
이것은 다른 답변보다 훨씬 최신이지만 2018 년 현재 코드에 다른 영향을 미치지 않고 한 줄로 작업을 수행하는 것이 가장 우아합니다.
Herick

1
이것은 좋은 것입니다. 그래도 NodeJS 7.6.0 이상을 사용해야합니다. 이전 버전에서는 작동하지 않습니다.
Ryan Shillington

5
let sleep = require('util').promisify(setTimeout);3 자 이상이지만 재사용 가능하고 읽기 쉬운 imo
BrianHVB

2
에 슬린 불만을 피하려면 resolve대신 전화하십시오 done. 즉await new Promise(resolve => setTimeout(resolve, 5000))
대런 쿡

150

setTimeout콜백 내에 지연 후 실행하려는 코드를 넣으십시오 .

console.log('Welcome to My Console,');
setTimeout(function() {
    console.log('Blah blah blah blah extra-blah');
}, 3000);

2
특히 OP가 나머지 지연 후에 프로그램의 나머지 부분을 실행하려는 경우에는 매우 지저분하고 일반적으로 나쁜 습관입니다. 내 대답을 참조하십시오.
Elliot Bonneville

32
@ElliotBonneville 개념을 설명하기위한 예제 일뿐입니다. 분명히 다른 곳과 마찬가지로 인라인 코드를 사용하는 대신 코드를 함수 호출로 인수화할 수 있습니다.
JohnnyHK

@ChristopherKemp : Node.js에 대한 솔루션이 node-fibers있습니다. 확인 해봐.
Elliot Bonneville

이는 특히 코드를 실행하지 않으려는 경우 루프 내에서 "슬립 (sleep)"메서드를 모방하려는 경우에 유용한 솔루션입니다. 이 예제에는 문제가 없습니다.
Halfstop

이 클라이언트에서 오는 요청에 지연에 적합합니다, 나는 클라이언트 측에서 내 로딩 스피너를 테스트하기 위해이 방법을 사용
모아 인 히미에게

145

이것은 간단한 차단 기술입니다.

var waitTill = new Date(new Date().getTime() + seconds * 1000);
while(waitTill > new Date()){}

그건 차단 다른 것도 (콜백 같은) 스크립트에서 일어날 것 인 한. 그러나 이것은 콘솔 스크립트이기 때문에 아마도 필요한 것입니다!


27
끔찍한 지 아닌지, 단순하고 wait, 차단하고 테스트 목적으로 작동합니다. 정확히 내가 찾던 것.
Clijsters

8
타사 라이브러리없이 질문에 완벽하게 대답하며 간단합니다. 그러나 사람들은 "끔찍한"이 ....이 Btw는 등이 매우 유사 무거운 CPU 부하를 시뮬레이션 좋은 예라고 phpied.com/sleep-in-javascript
돈 치들을

2
또한 이벤트 루프의 속도를 늦추어 다른 사용자 / 연결 속도를 늦추는 것을 시뮬레이션하려는 경우 필요한 접근 방법입니다. 지연된 콜백을 추가해도 다른 사용자 / 연결에는 영향을 미치지 않습니다.
Don Cheadle

13
이것은입니다 spin-wait.
Mike Atlas

7
@Ali 그것이 목표 인 것 같습니다.
Félix Gagnon-Grenier

63

노드 7.6.0 이상에서

노드는 기본적으로 대기를 지원합니다.

const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));

그런 다음 비동기 기능을 사용할 수 있다면 :

await sleep(10000); // sleep for 10 seconds

또는:

sleep(10000).then(() => {
  // This will execute 10 seconds from now
});

이전 노드 버전 (원래 답변)

CPU가 오래 걸리지 않고 Windows 및 Linux에서 작동하는 비동기 절전 모드가 필요했습니다. 절전 패키지를 시도했지만 Windows 상자에 설치되지 않았습니다. 나는 다음을 사용하여 끝났다.

https://www.npmjs.com/package/system-sleep

설치하려면 다음을 입력하십시오.

npm install system-sleep

귀하의 코드에서

var sleep = require('system-sleep');
sleep(10*1000); // sleep for 10 seconds

매력처럼 작동합니다.


1
훌륭한 답변 감사-불가능한 코드를 만들었습니다-이것은 스핀 대기가 아닙니다
danday74

1
추가 연구 에서이 모듈은 다른 비동기 github 저장소에서 분기 된 deasync에 의존합니다. 원래의 저장소는 해킹이므로 사용하지 말 것을 경고합니다. 그것은 작동하지만 모든 플랫폼에서 작동하지는 않으므로 크로스 플랫폼 솔루션이 필요한 경우이를 피하십시오.
danday74

1
예, 나는 그것에 대한 문제를 결코 경험하지 않았으며 개발자에게 큰 도움이되었습니다. -실패하면 시스템 슬립은 스핀 대기 상태로 돌아가 코드 실행을 정지
시킵니다.

1
이 패키지는 Mac OS에서 작동하지 않으므로 상호 호환되지 않으므로 작동 할 수 없습니다. github.com/jochemstoel/nodejs-system-sleep/issues/4
nuzzolilo를

1
@Nuzzolilo 이상합니다. 맥 오에스에는 한 명의 개발자가 있는데, 아무 잘못도 언급하지 않았다. 특정 Mac OS 버전 인 것 같습니다. sleep은 기본적으로 최신 버전의 NodeJS에 내장되어 있기 때문에이 답변을 업데이트했습니다.
Ryan Shillington

62

현대적인 자바 스크립트를 사용한 단순하고 우아한 수면 기능

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

의존성, 콜백 지옥 없음; 그게 다야 :-)


질문에 주어진 예를 고려할 때 두 콘솔 로그 사이에서 잠자기하는 방법입니다.

async function main() {
    console.log("Foo");
    await sleep(2000);
    console.log("Bar");
}

main();

"단점"은 이제 당신의 주요 기능이되어야한다는 async것입니다. 그러나 현대 Javascript 코드를 이미 작성하고 있다고 생각하면 코드 전체에서 async/를 사용하고 있거나 적어도 await문제가되지는 않으므로 실제로는 문제가되지 않습니다. 오늘날 모든 최신 브라우저가 이를 지원 합니다.

팻 화살표 연산자에 sleep익숙하지 않은 사람들을 위해 함수에 대한 약간의 통찰력을 제공하는 async/await, 이것은 그것을 작성하는 자세한 방법입니다.

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

그러나 팻 화살표 연산자를 사용하면 더 작고 우아합니다.


1
또한 수면 기능을 쓸 수 있으며 async다른 모든 것을 그대로 두십시오. 아마 더 명확 할 것입니다 async.
Kevin Peña

잘 잡아라, @ KevinPeña. 사실, 나는 그것없이 그것을 선호한다고 생각합니다 async. 당신의 제안으로 내 대답을 편집했습니다. 코드가 더 명확하지 않다고 생각합니다. 이를 위해 JSDoc을 대신 사용했습니다.
Lucio Paiva

8
나는 내 스크립트에 다음과 같은 한 줄짜리를 갖고 싶습니다.const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
korya


34

이 질문은 상당히 오래되었지만 최근 V8에는 OP가 요청한 것을 수행 할 수있는 생성기가 추가되었습니다. 생성기는 일반적으로 일시 중단 또는 gen-run 과 같은 라이브러리의 도움으로 비동기식 상호 작용에 사용하기 가장 쉽습니다. .

다음은 suspend를 사용하는 예입니다.

suspend(function* () {
    console.log('Welcome to My Console,');
    yield setTimeout(suspend.resume(), 10000); // 10 seconds pass..
    console.log('Blah blah blah blah extra-blah');
})();

관련 독서 (부끄러운 자기 진흥을 통한) : 제너레이터와의 큰 거래는 무엇입니까? .


2
좋은 답변-그러나 읽어야합니다yield setTimeout(suspend.resume(), 10000);
edhubbell

1
감사합니다, @edhubbell. 이 답변은 매우 오래된 버전의 일시 중지에 기반한 것이지만 최신에 관한 것은 옳습니다. 답변을 업데이트하겠습니다.
jmar777

어떤 버전의 노드입니까?
danday74

1
@ danday74 플래그가 지정되지 않았을 때를 정확하게 기억할 수는 없지만 --harmony플래그 뒤에 v0.12 이후에 있었고 node.green 에 따르면 v4.8.4 이후에는 플래그가 없어도 사용할 수 있습니다. node.green/#ES2015-functions-generators-basic-functionality . 그러나 새로운 async/await구문은와 같은 추가 라이브러리가 없어도 더 나은 솔루션을 제공합니다 suspend. 예제는 stackoverflow.com/a/41957152/376789 이 답변을 참조하십시오 . v7.10부터 비동기 함수를 사용할 수 있습니다 (플래그없이).
jmar777

20

Linux / nodejs에서 이것은 나를 위해 작동합니다.

const spawnSync = require ( 'child_process'). spawnSync;

var sleep = spawnSync ( '수면', [1.5]);

차단 중이지만 통화 중 대기 루프가 아닙니다.

지정하는 시간은 초 단위이지만 분수 일 수 있습니다. 다른 OS에 비슷한 명령이 있는지 모르겠습니다.


sleep유닉스 초기의 en.wikipedia.org/wiki/Sleep_%28Unix%29 이래로 거의 전능하고 실용적인 arround 입니다. 그것은 아마 존재하지 않을 OS 전용 "희소"당신이 시도 할 수 있지만이 (창입니다child_process.spawnSync('timeout', ['/T', '10'])
humanityANDpeace

17

"골프 코딩"을 원한다면 여기에 다른 답변 중 더 짧은 버전을 만들 수 있습니다.

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

그러나 실제로 제 생각에 이상적인 대답은 Node의 util라이브러리와 그 promisify기능을 사용하는 것입니다.이 기능은 정확히 이런 종류의 것을 위해 설계되었습니다 (기존의 비 약속 기반의 약속 기반 버전 만들기).

const util = require('util');
const sleep = util.promisify(setTimeout);

두 경우 모두 다음을 사용 await하여 sleep함수 를 호출하여 간단히 일시 중지 할 수 있습니다 .

await sleep(1000); // sleep for 1s/1000ms

실제로 util.promisify를 사용하면 콜백을 제공하지 않고 절전 모드를 호출 할 수 없습니다. nodejs.org/api/…
Howie

1
을 (를) 누락했습니다 await. 일종의 콜백을 생성하고 일시 중지 한 다음 해당 콜백이 반환되면 코드를 다시 시작합니다. 콜백은 값과 함께 반환되지만이 경우에는 신경 쓰지 않으므로 왼쪽에 아무것도 없습니다 await.
machineghost

1
코드 골프를 와인으로 만들기 위해 한 줄로 작성하십시오; const sleep = require ( 'util'). promisify (setTimeout);
Fabian

14

최근에 wait.for 라는 간단한 추상화를 만들어 동기화 모드에서 노드 함수를 기반으로 비동기 함수를 호출했습니다. 다가오는 ES6 Generator를 기반으로하는 버전도 있습니다.

https://github.com/luciotato/waitfor

wait.for를 사용하면 노드의 이벤트 루프를 차단하지 않고 표준 nodejs 비동기 함수를 동기화 함수처럼 호출 할 수 있습니다.

필요할 때 순차적으로 코딩 할 수 있습니다. 즉, 개인적 사용을 위해 스크립트를 단순화하기에 완벽합니다.

사용 뭘요 코드하는 것입니다 :

require('waitfor')

..in a fiber..
//start-of-code
console.log('Welcome to My Console,');
wait.miliseconds(10*1000); //defined in waitfor/paralell-tests.js - DOES NOT BLOCK
console.log('Blah blah blah blah extra-blah');
//endcode. 

또한 모든 비동기 함수는 동기화 모드 에서 호출 될 수 있습니다 . 예제를 확인하십시오.


TypeError: Object #<Object> has no method 'miliseconds'
CaffeineAddiction

코멘트는 말합니다 : "//waitfor/paralell-tests.js에 정의되어 있습니다"는 해당 파일에서 가져옵니다.
Lucio M. Tato

2
그것을 얻은 후에 wait.for/paralell-tests.js정의되지 않은 속성 등과 관련된 또 다른 오류가 발생했습니다. 따라서 복사해야했습니다. 이것이 필요하지 않은 방식으로 코드를 구성하지 않는 이유는 무엇입니까?
user907860

Wait.for 및 기타 파이버 솔루션이 완전히 새로운 세상을 열었습니다! 내가 할 수 있다면 나는 이것을 백만 번 투표했습니다. 대부분의 nodejs 커뮤니티는 파이버를 반대하지만, 이들은 환상적인 추가 요소이며 콜백 지옥과 관련하여 확실히 자리를 차지할 것이라고 생각합니다.
Levi Roberts

7

javascript 엔진 (v8)은 이벤트 큐의 이벤트 순서에 따라 코드를 실행하므로 지정된 시간 이후에 javascript가 정확하게 실행을 트리거하는 것은 엄격하지 않습니다. 즉, 나중에 코드를 실행하기 위해 몇 초를 설정하면 트리거링 코드는 순전히 이벤트 큐의 순서를 기반으로합니다. 따라서 코드 실행을 트리거하는 데 지정된 시간보다 오래 걸릴 수 있습니다.

따라서 Node.js는 다음과 같습니다.

process.nextTick()

나중에 setTimeout () 대신 코드를 실행하십시오. 예를 들어

process.nextTick(function(){
    console.log("This will be printed later");
});

2

ES6 지원을 통해 Promise타사 지원없이 사용할 수 있습니다.

const sleep = (seconds) => {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, (seconds * 1000));
    });
};

// We are not using `reject` anywhere, but it is good to
// stick to standard signature.

그런 다음 다음과 같이 사용하십시오.

const waitThenDo(howLong, doWhat) => {
    return sleep(howLong).then(doWhat);
};

doWhat함수는에서 resolve콜백이됩니다 new Promise(...).

또한 이것은 비동기 수면입니다. 이벤트 루프를 차단하지 않습니다. 차단 수면이 필요한 경우 C ++ 바인딩의 도움으로 차단 수면을 실현하는이 라이브러리를 사용하십시오. (비동기 환경과 같은 노드에서 블로킹 절전이 필요한 경우는 드 rare니다.)

https://github.com/erikdubbelboer/node-sleep


1
let co = require('co');
const sleep = ms => new Promise(res => setTimeout(res, ms));

co(function*() {
    console.log('Welcome to My Console,');
    yield sleep(3000);
    console.log('Blah blah blah blah extra-blah');
});

위의 코드는 자바 스크립트의 비동기 콜백 지옥 문제 해결의 부작용입니다. 이것이 또한 자바 스크립트를 백엔드에서 유용한 언어로 만드는 이유이기도합니다. 실제로 이것은 현대 자바 스크립트에 도입 된 가장 흥미로운 개선 사항입니다. 작동 방식을 완전히 이해하려면 발전기 작동 방식을 완전히 이해해야합니다. functiona로 다음 키워드는 *현대 자바 스크립트의 생성 기능이라고합니다. npm 패키지 co는 생성기를 실행하기위한 러너 기능을 제공했습니다.

본질적으로 생성기 함수는 생성기 함수 yield에서 키워드 를 사용하여 함수의 실행을 일시 중지하는 방법을 제공 yield했으며 생성기 내부와 호출자 사이에서 정보를 교환 할 수있었습니다. 이는 호출자가 promise비동기 호출에서 데이터를 추출 하고 확인 된 데이터를 생성기로 다시 전달 하는 메커니즘을 제공했습니다 . 효과적으로 비동기 호출을 동 기적으로 만듭니다.


이 코드는 질문에 대답 할 수 있지만 문제를 해결하는 방법 및 / 또는 이유에 대한 추가 컨텍스트를 제공하면 답변의 장기적인 가치가 향상됩니다.
Donald Duck

@DonaldDuck에게 감사합니다. 내 대답의 코드는 아마도 Javascript 개선의 가장 흥미로운 부분 일 것입니다. 일부 슈퍼 똑똑한 사람들이 콜백 지옥 문제를 해결하기 위해이 방법에 대해 생각한다는 사실에 놀랐습니다.
Qian Chen

1

이것은 @ atlex2가 제안한 더티 차단 접근 방식 에 기반한 moment.js 특징 모듈 입니다. 테스트 용도로만 사용하십시오 .

const moment = require('moment');

let sleep = (secondsToSleep = 1) => {
    let sleepUntill = moment().add(secondsToSleep, 'seconds');
    while(moment().isBefore(sleepUntill)) { /* block the process */ }
}

module.exports = sleep;

0

테스트 목적으로 일시 중단 해야하는 경우 현재 스레드 실행을 시도하십시오.

function longExecFunc(callback, count) {

    for (var j = 0; j < count; j++) {
        for (var i = 1; i < (1 << 30); i++) {
            var q = Math.sqrt(1 << 30);
        }
    }
    callback();
}
longExecFunc(() => { console.log('done!')}, 5); //5, 6 ... whatever. Higher -- longer

0

간단하게 우리는 어떤 이벤트가 발생할 때 (코드의 다른 곳에서 done 변수가 true로 설정되어 있음을 나타냄) 또는 시간 초과가 끝나면 100ms마다 점검 할 때까지 5 초 동안 기다립니다.

    var timeout=5000; //will wait for 5 seconds or untildone
    var scope = this; //bind this to scope variable
    (function() {
        if (timeout<=0 || scope.done) //timeout expired or done
        {
            scope.callback();//some function to call after we are done
        }
        else
        {
            setTimeout(arguments.callee,100) //call itself again until done
            timeout -= 100;
        }
    })();


0

이러한 모든 setTimeout, sleep 및 기타 많은 작업을 수행하는 대신 사용하는 것이 좋습니다

const delay = require('delay');
await delay(2000); // will wait for 2 seconds before executing next line of code

'지연'이 무엇인지 설명하고 해당 문서에 링크 할 수 있습니까? 왜 더 낫습니까?
boycy

-2

다른 답변은 훌륭하지만 다른 전략을 취할 것이라고 생각했습니다.

정말로 당신이 찾고있는 모든 것이 리눅스에서 특정 파일을 느리게하는 것입니다 :

 rm slowfile; mkfifo slowfile; perl -e 'select STDOUT; $| = 1; while(<>) {print $_; sleep(1) if (($ii++ % 5) == 0); }' myfile > slowfile  &

노드 myprog slowfile

5 줄마다 1 초간 잠자기 상태입니다. 노드 프로그램은 기록기만큼 느리게 진행됩니다. 다른 작업을 수행하는 경우 정상적인 속도로 계속 진행됩니다.

mkfifo는 선입 선출 파이프를 생성합니다. 이것이 작동하는 이유입니다. 펄 라인은 당신이 원하는대로 빨리 쓸 것입니다. $ | = 1은 출력을 버퍼링하지 않는다고 말합니다.


-3

이 질문에 대한 답변을 읽은 후 필요한 경우 콜백을 수행 할 수있는 간단한 함수를 모았습니다.

function waitFor(ms, cb) {
  var waitTill = new Date(new Date().getTime() + ms);
  while(waitTill > new Date()){};
  if (cb) {
    cb()
  } else {
   return true
  }
}

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