---
type: reference
language: javascript
slug: timer/set-timeout
title: "setTimeout() / setInterval() — 後で動かす"
title_tag: "JavaScript の setTimeout — 0 でも後になる理由と止め方"
summary: >
  0 ミリ秒を指定しても、いま動いている処理が終わるまで動きません。止め方、引数の渡し方、
  var で書いたループが全部同じ値になる理由、待つ関数の作り方まで実行して確かめます。
description: >
  setTimeout に 0 を渡しても即座には動きません。動く順番、clearTimeout での止め方、
  ループの中で値がずれる理由、try/catch で捕まえられないことまで実行して確かめられます。
status: published
difficulty: 2
minutes: 9

versions:
  verified: "Node 22.22.3"
  since: "ES2015"
  deprecated: null
  removed: null

sources:
  - title: "Timers — HTML Standard (WHATWG)"
    url: "https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers"
  - title: "Jobs and Host Operations — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-jobs"
  - title: "setTimeout() — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/API/Window/setTimeout"

terms: [タスク, マイクロタスク, 非同期, 閉包]

links:
  related:
    - javascript/reference/promise/promise
    - javascript/learn/function/scope
    - javascript/how-to/async/retry

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

**`0` を指定しても、すぐには動きません。**

```js run
const order = [];

setTimeout(() => order.push('timeout'), 0);
order.push('同期');

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

console.log(order.join(' -> '));
```
```output
同期 -> timeout
```

指定するのは「この時間で動く」ではなく、
[key:この時間が経ったら順番待ちに並ぶ]という意味です。

**いま動いている処理が終わるまで、順番は回ってきません。**

[dim:これは言語ではなく実行環境の仕組み（HTML Standard）ですが、Node にも同じものが入っています。]

## 動く順番

```js run
console.log('1 いますぐ');

setTimeout(() => console.log('4 タイマー'), 0);

Promise.resolve().then(() => console.log('3 マイクロタスク'));

console.log('2 いますぐ');

await new Promise((resolve) => setTimeout(resolve, 10));
```
```output
1 いますぐ
2 いますぐ
3 マイクロタスク
4 タイマー
```

| 順 | 何が動くか |
|---|---|
| 1 | **いま書いてある処理**（同期） |
| 2 | `Promise` の続き（[type:マイクロタスク]） |
| 3 | `setTimeout` で預けたもの（[type:タスク]） |

**`Promise` のほうが必ず先です。** `0` を指定しても変わりません。
→ [Promise — then / catch / finally と async / await](/ja/javascript/reference/promise/promise/)

## 止める

```js run
const id = setTimeout(() => console.log('これは出ない'), 5);

clearTimeout(id);

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

console.log('終わり');
```
```output
終わり
```

`setTimeout()` の返り値を取っておいて、`clearTimeout()` に渡します。

[bad:返り値の中身は環境によって違います。] ブラウザでは数値、Node では別の値です。
**中身を見たり、比べたり、保存したりしないでください。** 渡すだけにします。

## 引数を渡す

```js run
setTimeout((a, b) => console.log('引数:', a, b), 0, 1, 2);

await new Promise((resolve) => setTimeout(resolve, 10));
```
```output
引数: 1 2
```

第3引数から後ろが、そのまま関数に渡ります。
**閉包で渡せるので、いまはあまり使いません。**

## 待つ関数を作る

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

console.log('前');
await sleep(5);
console.log('後');
```
```output
前
後
```

**この3行が、非同期の待ち時間でいちばんよく使う形です。**
再試行の間隔を空けるときにも使います。
→ [失敗したら再試行する](/ja/javascript/how-to/async/retry/)

## `setInterval()` — 繰り返す

```js run
let count = 0;

const id = setInterval(() => {
  count++;
  if (count === 3) clearInterval(id);
}, 1);

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

console.log(count);
```
```output
3
```

**止めるまで動き続けます。** `clearInterval()` を必ず書いてください。

[bad:中の処理が指定した間隔より長いと、溜まっていきます。]
通信のように時間の読めない処理を繰り返すなら、
`setTimeout()` を終わるたびに掛け直すほうが安全です。

## よくある間違い

### `var` で書いたループ

```js bad
const out = [];

for (var i = 0; i < 3; i++) {
  setTimeout(() => out.push(i), 0);
}

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

console.log(out.join(' '));
```
```output
3 3 3
```

**全部 `3` になりました。**
`var` はループ全体で[key:1つしかない]ので、実際に動くころには `3` になっています。

`let` なら、**繰り返しごとに別の入れ物**になります。

```js run
const out = [];

for (let i = 0; i < 3; i++) {
  setTimeout(() => out.push(i), 0);
}

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

console.log(out.join(' '));
```
```output
0 1 2
```

→ [スコープと閉包 — 変数はどこから見えるか](/ja/javascript/learn/function/scope/)

### `try` で囲んでも捕まらない

```js
try {
  setTimeout(() => {
    throw new Error('中で落ちた');
  }, 0);
} catch (error) {
  // ここには来ない
}
```

`try` を抜けたずっと後に動くので、**この `catch` は無関係**です。
[dim:実際に走らせると捕まらないまま外へ出てしまうので、このページでは実行例にできません。]

囲むのは**中側**です。

```js run
setTimeout(() => {
  try {
    throw new Error('中で落ちた');
  } catch (error) {
    console.log('中で捕まえた:', error.message);
  }
}, 0);

await new Promise((resolve) => setTimeout(resolve, 10));
```
```output
中で捕まえた: 中で落ちた
```

→ [Error と try / catch / finally / throw](/ja/javascript/reference/error/error/)

### 指定した時間ちょうどに動くと思う

**指定できるのは[em:最短]の待ち時間だけです。**

- いま動いている処理が終わるまで待たされます
- 画面が裏に回っていると、間隔が延ばされることがあります
- 入れ子にしたタイマーには、下限が設けられています

**時間の計測や、正確な間隔が要る処理には使えません。**

## まとめ

- `0` を指定しても[key:いまの処理が終わってから]動く
- 順番は **同期 → `Promise` → タイマー**
- 返り値は `clearTimeout()` に渡すだけ。[bad:中身は環境で違う]
- `sleep` は `new Promise` と組にして作る
- `setInterval()` は**止めるまで動く**。時間の読めない処理には向かない
- `var` のループは全部同じ値になる。`let` を使う
- **外側の `try` では捕まえられない。** 中で囲む
- 指定できるのは[em:最短]の待ち時間だけ
