JavaScript

JavaScriptで一定時間待ってから処理を開始する方法

※当サイトにはプロモーションが含まれています。

投稿日:2016年6月11日 更新日:

1. はじめに

JavaScriptで一定時間待ってから何か処理を行いたい場合、setTimeout() を使うこともできるのですが、読みにくいコードになってしまいます。そこで、Promise を使って読みやすくしてみます。

Promise というのは、非同期処理を分かりやすいコードで記述できるように用意されたオブジェクトです。ブラウザごとの対応状況は、Promises | Can I use… で確認できますが、最近だとIE以外のブラウザであれば対応しているようです。

追記

更に時は進み、ECMAScript 2017 (ECMA-262) という仕様で「async function」という機能が追加されたことにより、より簡単に Promise が使えるようになりました。今後はこちらの利用が推奨されると思いますので、こちらの例を先に紹介します。

2. 手順(async function版)

まず、「指定された時間待つだけの関数を内包したPromiseオブジェクト」を返す関数を用意しておきます。

const wait = (sec) => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, sec*1000);
    //setTimeout(() => {reject(new Error("エラー!"))}, sec*1000);
  });
};

(一定時間待つ処理のために、setTimeout を実行しています。)

あとは、この「一定時間待つ関数」と「その後で実行したい処理」を「async を付けた関数」の中に順番に記述するだけです。

async function main() {
  try {
    await wait(10); // ここで10秒間止まります

    // ここに目的の処理を書きます。

  } catch (err) {
    console.error(err);
  }
}

main();

(エラー処理のために、try...catch を使っています。)

この後の「Promise をそのまま使った」場合と比べると、断然こちらの方が読みやすいと思います。

async / await のポイントを書いておきます。

async

  • 普通の関数の頭に async を付けると、その関数は Promise を返す関数になる。(Promiseオブジェクト以外を返す関数であっても、それを Promise でラップして返すようになる)
  • async を付けた関数内では、await が使えるようになる。
  • async を付けた関数自体は同期処理にならない。

await

  • Promiseオブジェクトの頭につけると、その Promiseオブジェクトが実行される。
  • その際、処理が終了するまで待って結果を受け取ることができる(同期処理になる)。
  • await が使えるのは、async を付けた関数の中だけである。

デモページを用意しました

3. 手順(Promise をそのまま使った版)

まず、「指定された時間待つだけの関数」を返す関数を用意しておきます。

var wait = function(sec) {
  return function() {
    return new Promise(function(resolve/*, reject*/) {
      setTimeout(resolve, sec*1000)
    });
  }
};

分かりづらいですが、setTimeoutPromise で包んでいます。

あとはPromiseを使って、この関数の後に本来の処理を実行するだけです。

Promise.resolve()
  .then(wait(10)) // ここで10秒待つ(「Promiseオブジェクトを返す関数」を thenに渡しています)
  .then(function() {

    // ここに目的の処理を書きます。

  })
  .catch(function (err) {
    console.error(err);
    self.result_message = error;
  });

デモページを用意しました

4. いつ使うのか?

例えば、ユーザがボタンをクリックした時に重い同期処理を開始し、終了するまでの間、ローディングアイコンを表示したい場合に使えます。
先日、素数判定(リンク切れ)を作った時に使いました。というか、それがあったからこのページを書きました。

通常、ローディングアイコンを表示してそのまま重い同期処理を開始しようとすると、ローディングアイコンが表示される処理が始まる前に重い処理が始まってしまい画面のレンダリングがブロックされてしまってアイコンが表示されません。なのでローディングアイコンが表示されるのを待ってから、メインの処理を開始するようにします。

参考

スポンサードリンク

📂-JavaScript
-,

執筆者:labo


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

JavaScript

JavaScript で「弱い参照」を作成する

JavaScript で「弱い参照」を作成する方法を紹介します。

JavaScript

JavaScript による HTTP(S)リクエスト送信のいろいろな書き方

目次1. はじめに2. JSON を取得するコード(1) axios (XMLHttpRequest) (基本形)(2) axios (XMLHttpRequest) (async/await を使用 …

JavaScript

JavaScript の静的インポートと動的インポート

目次1. JavaScript の 2種類のインポート機能(概要)1. モジュール側2. 呼び出し側2. 静的インポート1. この機能の呼び名2. 特徴3. 仕様4. ブラウザのサポート状況5. 使い …

JavaScript

【JavaScript】無名関数とアロー関数とイベントリスナーのthis

目次1. はじめに2. イベントリスナーの登録無名関数を使う場合アロー関数を使う場合3. まとめ4. 参考 1. はじめに あるHTMLにおいて、以下のようにボタンが存在しており、このボタンのクリック …

JavaScript

JavaScript からCSSカスタムプロパティを使用する(2パターン)

JavaScript からCSSカスタムプロパティを使用する(2パターン)方法について説明します。