> ## Documentation Index
> Fetch the complete documentation index at: https://docs.base44.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Internal links on these pages omit the .md extension. Append .md to a docs page URL, or send an Accept: text/markdown header, to get that page as markdown.

# アクター: サンプルフロー

> ライフサイクルハンドラー、タイマー、接続、ストレージ、エンティティ、バックエンド関数のサンプルフロー

<div className="dev-docs-banner">
  <div className="dev-docs-banner-content">
    <div className="dev-docs-banner-title">
      開発者向けドキュメントを表示しています
    </div>

    <div className="dev-docs-banner-text">
      このドキュメントは、Base44 開発者プラットフォームで作業する開発者向けです。
    </div>
  </div>
</div>

これらのサンプルフローを、実装の出発点として活用してください。

## クライアントをセッションに接続する

フロントエンドでライブセッションに参加し、アクターとメッセージを送受信する必要がある場合は、クライアントをアクターセッションに接続します。

**クライアントをセッションに接続するには:**

1. [`base44.actors.ActorName(sessionId)`](/ja/developers/references/sdk/docs/type-aliases/actors) を呼び出してセッションを選択します。
2. [`.connect()`](/ja/developers/references/sdk/docs/type-aliases/actors#connect) を呼び出して WebSocket 接続を開きます。
3. [`conn.subscribe()`](/ja/developers/references/sdk/docs/type-aliases/actors#subscribe) を呼び出して、アクターからのメッセージのリスナーを登録します。
4. [`conn.send()`](/ja/developers/references/sdk/docs/type-aliases/actors#send) を呼び出して、アクターにメッセージを送信します。

次の例では、`chatRoom` アクターのセッションに接続し、メッセージをリッスンして、メッセージを送信します。

```typescript theme={null}
const conn = base44.actors.chatRoom("lobby-1").connect();

conn.subscribe((msg) => {
  if (msg.type === "message") console.log(msg.text);
});

conn.send({ type: "message", text: "Hello" });
```

接続について詳しくは、[接続](/ja/developers/backend/resources/actors/reference#connections) を参照してください。

## tick を実行する

クライアントがセッションにいる間、一定の間隔で処理を繰り返す必要がある場合は、tick を実行します。たとえば、ゲームの状態のブロードキャストや、ラウンドのタイマーの更新です。

**tick を実行するには:**

1. [`tickIntervalMs`](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) に間隔の長さをミリ秒で設定します。
2. [`shouldTick()`](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) を実装し、tick を続ける場合は `true` を、停止する場合は `false` を返します。
3. [`handleTick()`](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) で、各間隔の処理を実行します。

次の例では、セッションに 2 つ以上のクライアントがいる間、毎秒 tick し、tick ごとにカウントダウンをブロードキャストします。

```typescript theme={null}
export default class Game extends Actor<Incoming, Outgoing> {
  tickIntervalMs = 1000;
  countdown = 60;

  shouldTick() {
    return this.getConnections().length >= 2;
  }

  async handleTick() {
    this.countdown--;
    this.broadcast({ type: "tick", countdown: this.countdown });
  }
}
```

tick について詳しくは、[タイマーハンドラーと設定](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) を参照してください。

## wake をスケジュールする

セッションがアクティブかアイドルかに関係なく、特定の時刻に 1 回処理を実行する必要がある場合は、wake をスケジュールします。たとえば、30 秒後のターン終了や、空のロビーのクローズです。

**wake をスケジュールするには:**

1. キーと時刻を指定して [`schedule()`](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) を呼び出し、wake を設定します。
2. [`handleWake()`](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) でキーを確認し、その wake の処理を実行します。
3. wake が不要になったら、キーを指定して [`cancelSchedule()`](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) を呼び出します。

次の例では、ターンの開始時にターンのタイムアウトをスケジュールし、タイムアウトがトリガーされるとメッセージをブロードキャストします。

```typescript theme={null}
export default class Game extends Actor<Incoming, Outgoing> {
  async handleMessage(_conn, msg) {
    if (msg.type === "start-turn") {
      await this.schedule("turn-timeout", Date.now() + 30_000);
    }
    if (msg.type === "end-turn") {
      await this.cancelSchedule("turn-timeout");
    }
  }

  async handleWake(key: string) {
    if (key === "turn-timeout") {
      this.broadcast({ type: "timeout" });
    }
  }
}
```

wake について詳しくは、[タイマーハンドラーと設定](/ja/developers/backend/resources/actors/reference#timer-handlers-and-settings) を参照してください。

## クライアント接続を管理する

セッションに参加できる人を決めたり、特定のクライアントに返信したり、セッション内のすべてのクライアントに送信したりする必要がある場合は、クライアント接続を管理します。

**クライアント接続を管理するには:**

1. [`handleConnect()`](/ja/developers/backend/resources/actors/reference#lifecycle-handlers) で [`conn.identity`](/ja/developers/backend/resources/actors/reference#connections) を確認し、[`conn.reject()`](/ja/developers/backend/resources/actors/reference#connections) を呼び出してクライアントを拒否します。
2. [`conn.send()`](/ja/developers/backend/resources/actors/reference#connections) を呼び出して、そのクライアントにのみ返信します。
3. [`handleMessage()`](/ja/developers/backend/resources/actors/reference#lifecycle-handlers) で [`broadcast()`](/ja/developers/backend/resources/actors/reference#connections) を呼び出し、接続中のすべてのクライアントに送信します。送信者を識別するには、`conn` のフィールドをメッセージに含めます。

次の例では、匿名のクライアントを拒否し、接続してきたクライアントに履歴を送信し、送信者のユーザー ID とともにメッセージをブロードキャストします。

```typescript theme={null}
async handleConnect(conn) {
  if (conn.identity.type === "anonymous") {
    conn.reject(401, "Login required");
    return;
  }
  conn.send({ type: "history", messages: this.messages });
}

async handleMessage(conn, msg) {
  this.broadcast({ type: "message", from: conn.identity.userId, text: msg.text });
}
```

接続について詳しくは、[接続](/ja/developers/backend/resources/actors/reference#connections) を参照してください。

## セッションデータを永続化する

値をアイドル期間後も残す必要がある場合は、セッションデータを永続化します。たとえば、盤面、履歴リスト、現在のターンです。

**セッションデータを永続化するには:**

1. [`handleStart()`](/ja/developers/backend/resources/actors/reference#lifecycle-handlers) で、[`this.storage`](/ja/developers/backend/resources/actors/reference#storage) から値をクラスフィールドに読み込みます。
2. 変更のたびに [`this.storage.put()`](/ja/developers/backend/resources/actors/reference#storage) を呼び出して、更新した値を保存します。
3. セッションをリセットするには、[`this.storage.delete()`](/ja/developers/backend/resources/actors/reference#storage) または [`this.storage.deleteAll()`](/ja/developers/backend/resources/actors/reference#storage) を呼び出します。

次の例では、開始時に盤面を読み込み、手ごとに保存し、最後のクライアントが切断したときにストレージをクリアします。

```typescript theme={null}
async handleStart() {
  this.board = (await this.storage.get<Board>("board")) ?? newBoard();
}

async handleMessage(_conn, msg) {
  applyMove(this.board, msg.move);
  await this.storage.put("board", this.board);
}

async handleClose(_conn) {
  if (this.getConnections().length === 0) {
    await this.storage.deleteAll();
  }
}
```

ストレージについて詳しくは、[ストレージ](/ja/developers/backend/resources/actors/reference#storage) を参照してください。

## セッションからエンティティデータを書き込む

セッションでアプリのレコードを作成または更新する必要がある場合は、エンティティデータを書き込みます。たとえば、最終スコアや完了した注文です。

**セッションからエンティティデータを書き込むには:**

1. 書き込む前に、受信メッセージを検証します。
2. [`conn.identity.userId`](/ja/developers/backend/resources/actors/reference#connections) からユーザー ID を読み取ります。
3. 昇格したアクセスには [`this.client.asServiceRole`](/ja/developers/backend/resources/actors/reference#entity-access) を使用します。セッション ID などの安定したキーで書き込むと、ハンドラーが繰り返し実行されても同じレコードが更新されます。

次の例では、認証済みのクライアントの最終スコアを保存します。同じセッションで後から保存すると、そのレコードが更新されます。

```typescript theme={null}
async handleMessage(conn, msg) {
  if (msg.type !== "save-score" || conn.identity.type !== "authenticated") return;
  if (typeof msg.score !== "number") return;

  const fields = {
    sessionId: this.instanceId,
    userId: conn.identity.userId,
    score: msg.score,
  };
  const [existing] = await this.client.asServiceRole.entities.Score.filter({
    sessionId: this.instanceId,
  });

  if (existing) {
    await this.client.asServiceRole.entities.Score.update(existing.id, fields);
  } else {
    await this.client.asServiceRole.entities.Score.create(fields);
  }
}
```

エンティティへのアクセスについて詳しくは、[エンティティへのアクセス](/ja/developers/backend/resources/actors/reference#entity-access) を参照してください。

## シークレットが必要な処理でバックエンド関数を呼び出す

アクターは [`secrets.get()`](/ja/developers/backend/resources/actors/reference#read-secrets) でアプリのシークレットを読み取れます。API キーを使って外部 API を呼び出すなど、ハンドラーでシークレットを使う処理が必要な場合は、[バックエンド関数](/ja/developers/backend/resources/backend-functions/overview) を呼び出すことをおすすめします。関数はシークレットを読み取り、シークレットではなく結果を返します。

**アクターからバックエンド関数を呼び出すには:**

1. `secrets.get()` でシークレットを読み取り、処理を行って結果を返すバックエンド関数を作成します。
2. ハンドラーで、関数名と送信するデータを指定して [`this.client.functions.invoke()`](/ja/developers/references/sdk/docs/interfaces/functions#invoke) を呼び出します。
3. 結果をセッションで使用します。たとえば、接続中のクライアントにブロードキャストします。

次の例は、API キーを読み取って翻訳を返すバックエンド関数です。

```typescript theme={null}
// base44/functions/translateText/entry.ts
import { secrets } from "base44:runtime";

export default async function (req: Request): Promise<Response> {
  const { text } = await req.json();
  const apiKey = secrets.get("TRANSLATE_API_KEY");

  const res = await fetch("https://api.example.com/translate", {
    method: "POST",
    headers: { Authorization: `Bearer ${apiKey}` },
    body: JSON.stringify({ text }),
  });
  const { translation } = await res.json();

  return Response.json({ translation });
}
```

次の例では、アクターからその関数を呼び出し、結果をブロードキャストします。

```typescript theme={null}
export default class ChatRoom extends Actor<Incoming, Outgoing> {
  async handleMessage(_conn, msg) {
    const result = await this.client.functions.invoke("translateText", { text: msg.text });
    this.broadcast({ type: "message", text: result.data.translation });
  }
}
```

## 関連項目

* [アクター概要](/ja/developers/backend/resources/actors/overview): 概念と用語
* [アクターを作成する](/ja/developers/backend/resources/actors/create-actor): アクターファイルと最小限のクラス
* [アクターのファイルとコード](/ja/developers/backend/resources/actors/reference): バックエンドクラス API の完全なリファレンス
* [`actors deploy`](/ja/developers/references/cli/commands/actors-deploy): ローカルのアクターをデプロイします

<Note>このページは AI によって翻訳されました。最も正確で最新の情報については、[英語版](/) を参照してください。</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.