-->

JavaScriptでn秒間待機する方法(sleep処理)

n秒待機する(ES2017対応async/await)

// ミリ秒間待機する
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
//const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

async function main() {
  console.log('start');
  await sleep(1*1000);

  console.log(0);
  await sleep(1*1000);

  console.log(1);
  await sleep(1*1000);

  for (var i=2; i<5; i++) {
    console.log(i);
    await sleep(1*1000);
  }

  console.log('end');
};
main();

async/awaitが使用できるのであれば、これで決まりです。

n秒待機する(ES2015対応Generator)

// ミリ秒間待機する
function sleep(ms, generator) {
  setTimeout(() => generator.next(), ms);
}

var main = (function*() {
  console.log('start');
  yield sleep(1*1000, main);

  console.log(0);
  yield sleep(1*1000, main);

  console.log(1);
  yield sleep(1*1000, main);

  for (var i=2; i<5; i++) {
    console.log(i);
    yield sleep(1*1000, main);
  }

  console.log('end');
})();
main.next();

ジェネレータ関数を利用した処理です。コードはきれいですが、使用できるかどうかは、対応環境次第です。

n秒待機する(ES2015対応Promise)

// ミリ秒間待機する
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
//const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

function main() {
  let promise = Promise.resolve();

  promise = promise.then(() => {
    console.log('start');
    return sleep(1*1000);
  }).then(() => {
    console.log('0');
    return sleep(1*1000);
  }).then(() => {
    console.log('1');
    return sleep(1*1000);
  });

  for (var k=2; k<5; k++) {
    // クロージャーを利用した変数の受け渡し
    promise = promise.then((function(i) {
      return () => {
        console.log(i);
        return sleep(1*1000);
      };
    })(k));
  }

  promise.then(() => {
    console.log('end');
  });
};
main();

Promiseを利用した処理です。メソッドチェーンによる対応です。forループや変数の受け渡しの処理が複雑になります。

n秒待機する(setTimeout)

// ミリ秒間待機する
function sleep(ms, func) {
  setTimeout(func, ms);
}

function main() {
  console.log('start');
  sleep(1*1000, function() {
    console.log('0');

    sleep(1*1000, function() {
      console.log('1');

      sleep(1*1000, function() {
        console.log('2');

        sleep(1*1000, function() {
          console.log('3');

          sleep(1*1000, function() {
            console.log('4');

            sleep(1*1000, function() {
              console.log('end');
            });
          });
        });
      });
    });
  });
};
main();

世にいうコールバック地獄です。関数の入れ子構造が積み重なり、コードがどんどんと読みにくくなっていきます。

n秒待機する(XMLHttpRequest)

// n秒間待機する
function sleep(n) {
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n='+n, false);
  request.send(null);
}

function main() {
  console.log('start');
  sleep(1);

  console.log(0);
  sleep(1);

  console.log(1);
  sleep(1);

  for (var i=2; i<5; i++) {
    console.log(i);
    sleep(1);
  }

  console.log('end');
};
main();
sleep.php<?php sleep($_GET['n']);

サーバ側の待機処理を利用して、リクエストを同期処理することで実現します。ただし、通信環境次第では、待機時間は想定より長くなる可能性がある。また、使用範囲によってはサーバ側にリクエストが無為に集中する問題があります。

n秒待機する(ループ)

// ミリ秒間待機する
function sleep(ms) {
  var time = new Date().getTime() + ms;
  while (new Date().getTime() < time) {}
}

function main() {
  console.log('start');
  sleep(1*1000);

  console.log(0);
  sleep(1*1000);

  console.log(1);
  sleep(1*1000);

  for (var i=2; i<5; i++) {
    console.log(i);
    sleep(1*1000);
  }

  console.log('end');

};
main();

この方法は、CPUの処理能力を無為に消費するため、採用すべきではありません。

補足

参考

コメント