JavaScript Promiseの実行タイミング Promise.start() とか Promise.execute() 的なもの


# Promiseには .start() .execute() が存在しない

Promise objectを作ってtaskを設置したとき、発火方法がわからなかった。

イメージとしては ↓ だったんだけど

```js
const task = new Promise(()=>{ // task});
task.start() // こんなものはない
```

Promiseにそんなmethodはなかった。使えるのは６つだけ。

> 1. Promise`.all`(promises)
2. Promise`.allSettled`(promises)
3. Promise`.race`(promises)
4. Promise`.any`(promises)
5. Promise`.resolve`(value)
6. Promise`.reject`(error)

> https://javascript.info/promise-api

`Promiseは Object を作った瞬間に start() するものだった！！`

1. 関数の中なら、関数が呼ばれると、Promise objectが生成される ＝ 実行される
2. MAIN関数や &lt;script&gt; の直下なら file loadした瞬間に Promise objectが生成される = 即実行される


# 発火のコントロール方法

まずPromiseの宣言方法(というか、使い方） は２つ。

1. Object(変数)として作る
2. `関数の中`に作る（これを個人的には `関数として作る` と言いたい）


↓では最初の３つ(a, b, c)が変数、残りが関数(d, e) で書いている。


```html
<script>

// awaitを中で使うので、この start() は async で宣言する
const start = async () => {

	//////////////////////////////////////////////////////
	// (a) objectだと宣言した瞬間に実行される
	const objImmediately = new Promise((resolve) => {
		resolve();
		console.log("(a) objImmediately done");
	});

	// (b) objectだと宣言した瞬間に実行される
	const objImmediatelyWithSleep = new Promise((resolve) => {
		setTimeout(()=>{
			resolve();
			console.log("(b) objImmediatelyWithSleep done");
		}, 400)
	});

	// (c) object宣言とともに実行 & awaitでこれより下の行を一時停止する
	const objImmediatelyAndAwait = await new Promise(async (resolve) => {
		await setTimeout(async ()=>{
			resolve();
			console.log("(c) objImmediatelyAndAwait done");
		}, 300)
	});


	// (d) 関数の中で Promise objectを作る。生成即実行かと思いきや、関数が呼ばれるまでは実行されない。
	const funcLater = async () => {
		await new Promise(async (resolve) => {
			setTimeout(()=>{
				resolve();
				console.log("(d) funcLater done");
			}, 200)
		});
	}

	// (e) これも関数の中なので即実行されない。Promiseをreturnすると then が使える
	const funcLaterReturnPromise = async () => {
		return await new Promise((resolve) => {
			setTimeout(()=>{
				resolve();
				console.log("(e) funcLaterReturnPromise done");
			}, 100)
		});
	}


	// MAIN ////////////////////////////////////////////////////

	// (a, b, c) objectは関数ではないのでできない & 不要
	// objImmediately()
    // objImmediatelyWithSleep()
	// objImmediatelyAndAwait()


	// (d) 関数を呼ぶ = promiseが初めて実行される
	await funcLater();

	// 返り値がないので then はできない
	// await funcLater().then(()=>{console.log("then")});
	// Uncaught (in promise) TypeError: Cannot read property 'then' of undefined

	// (e) 返り値がpromiseだとチェーンできる
	await funcLaterReturnPromise()
	.then(
		()=>{console.log("(e) then")
	});

	console.log("(f) Finished.");
}

start();
</script>
```

近頃は猫も杓子も promise をreturnしてくるので、async関数じゃないとコールすらできなかったりする。
(start()関数がわざわざ async function になってるのは中で awaitを使ってるから）

### result

```java
(a) objImmediately done
(c) objImmediatelyAndAwait done
(b) objImmediatelyWithSleep done
(d) funcLater done
(e) funcLaterReturnPromise done
(e) then
(f) Finished.
```

## 発火順 と 完了順

x = 発火
o = 実行中

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/c741f05e-d46b-11fb-8847-94ad0b5e29c1.png)

objectの３つは宣言 即 実行されている。

関数の2つはその後で call されている。

発火順は上から下に a-e だ。
だけど、awaitが絡んで完了順は C が B を追い越している。その他は順番通り。
肝は、d&eのsleepがb&cより短いのに、d&eはb&cより後に完了する点だ。これは単純に発火を遅らせて実現している。


(c) がobjectだけどawaitしているので、(d)は (c) が終わるまで待っている。

(e) は (d) が終わるまで待っている。


# まとめ

1. Promise を objectとしてコールすると、即実行される。
2. Promiseの発火タイミングをコントロールしたかったら、関数の中で宣言する。 `関数をいつ呼ぶか` でコントロールする。

直接 new Promise してるコードを見たら `その関数がいつ呼ばれたか` を知らないと即実行されたタイミングがわからない。外側の関数を見に行く必要がある。しかし大概そこでも new Promiseされている。さらに外側の関数を見に行くことになる。

僕らは無限のPromise地獄の中でもがいているのだ。