JavaScriptのPromise、asyncの決まり事，awaitと .then() の関係

JavaScriptで非同期処理をするときに一番使われる技術に「Promise」「async」「await」があります。本記事は、その基本として「なぜ必要なのか」を分かりやすく解説します。また、これらを使う際の“決まりごと”や“使い方の型”も紹介します。

# 非同期処理とは

JavaScriptは基本的に1本のスレッド(単線)で動作します。
たとえばネットワーク経由のAPI呼び出しなど、答えが返ってくるまで時間がかかる処理を直接動かすと、他の処理が止まってしまいます。

そこで、JavaScriptは "非同期" にする方法として `Promise` という構造を用意しています。

## Promiseとは

Promiseは、一言で言うと「後で答えが返ってくるボックス」です。

### Promiseの基本形
```javascript
function doSomethingAsync() {
  return new Promise((resolve, reject) => {
    // 非同期な処理
    setTimeout(() => {
      resolve("成功");
    }, 1000);
  });
}
```

### 使い方: `.then()`
```javascript
doSomethingAsync().then(result => {
  console.log(result); // => "成功"
}).catch(error => {
  console.error(error);
});
```

### async/awaitはPromiseの簡単表現

`.then()` を使うと処理がネストして書きづらくなることがあります。

`async`/`await` を使うと、一要する「Promiseをまるで普通の値のように書ける」ようになります。

#### 例:
```javascript
async function run() {
  try {
    const result = await doSomethingAsync();
    console.log(result); // => "成功"
  } catch (error) {
    console.error(error);
  }
}
```

## awaitの特徴と「決まりごと」

**✅ `await` は Promise を「待つ」ためのもの**
```javascript
const result = await somePromise();
```

**✅ `await` は `async function` の中でしか使えない**
```javascript
// ❌ エラーになる例
const result = await somePromise(); // async function の外では使えない

// ✅ 正しい例
async function getResult() {
  const result = await somePromise();
  return result;
}
```

**✅ `await` の対象が普通の値でもOK（即座に返る）**
```javascript
const x = await 42;        // OK, x === 42
const y = await "Hello";  // OK, y === "Hello"
```
**✅ Promiseが返る関数を「呼び出す側」は `await` か `.then()` で結果を処理**
```javascript
// 関数定義
function fetchData() {
  return new Promise(resolve => setTimeout(() => resolve("done"), 1000));
}

// 呼び出し
const result = await fetchData();     // ✅ await方式
fetchData().then(result => {...});    // ✅ .then()方式
```
**❌ よくある間違い**
```javascript
const result = fetchData();
console.log(result); // Promiseオブジェクトが出てきて中身が取れない
```

## callback型APIをPromise化する理由

コールバック型APIは結果を `return` ではなく `callback(result)` として返します。

**悪い例:**
```javascript
function getValue() {
  let result;
  chrome.storage.sync.get(["token"], (data) => {
    result = data.token;
  });
  return result; // => undefined!
}
```
**よい例 (Promise化)**
```javascript
function getValue() {
  return new Promise((resolve) => {
    chrome.storage.sync.get(["token"], (data) => {
      resolve(data.token);
    });
  });
}

const token = await getValue();
```

### 補足：.then()とawaitの違いと使いどころ

Promiseの結果は .then() または await で受け取ることができますが、使い方には違いがあります。

#### `.then()` の中でしか値を扱えない理由

`.then()` は非同期処理が完了したときに実行されるコールバックです。そのため、その中でしか値を安全に使えません。
```javascript
let result;
getValue().then(res => {
  result = res;
});
console.log(result); // ❌ まだundefinedのまま
```
#### `await` を使うと「一時停止してから処理を続ける」

`await` は Promise が解決するのを待ち、その結果をまるで変数のように受け取れます。
```javascript
const result = await getValue();
console.log(result); // ✅ 正しく値が取れる
```

**`await` は `.then()` の Syntax Sugar**

`await` は内部的には `.then()` を使って処理しています。ただし `await` を使うことで、コードを同期的に書けて可読性が上がります。
`async function` の内部全体は Promise の中に包まれています。そのため `await` で「いったん止まる」→「続きが `.then()` の中身と同様に動く」という流れになります。

### asyncをつける必要があるか

**asyncが必要なのは:**
- 関数内で `await` を使う場合
- 普通の値を `Promise` として自動的に返したい場合（syntactic sugar）

**asyncが不要なのは:**
- すでに `return new Promise(...)` している場合
- 内部で `await` を使わない場合

## 総まとめ：使い方の“型”

**✅ Promiseを返す関数の作り方**
```javascript
function getData() {
  return new Promise((resolve, reject) => {
    resolve("OK");
  });
}
```
**✅ async/awaitで呼び出す**
```javascript
async function main() {
  const result = await getData();
  console.log(result);
}
```
**✅ async/awaitとthenの併用も可能（ただし可読性に注意）**
```javascript
async function main() {
  getData().then(result => console.log(result));
  // or
  const result = await getData();
}
```
## 総結
|技術|使用目的|
|-|-|
|`Promise`|非同期な処理をラップする|
|`.then()`|Promiseの結果を受け取る|
|`async`|関数を Promiseを返すようにする／内部でawaitを使うために必要|
|`await`|Promiseの結果を待って使う|

Promiseやasync/awaitを理解すると、JavaScriptの非同期処理がとても読みやすく、書きやすくなります。