Prompt

JSのPromiseにあたるものはRustでは?

JSのPromiseに相当するものは、Rustでは Future と呼ばれるよ!

そして、JSでおなじみの async / await 構文も、Rustにはバッチリ備わっているんだ。

でも、情報工学的に見ると、Rustの Future はJSの Promise よりもずっと**「低燃費で効率的」**に設計されているんだ。その決定的な違いと仕組みを解説するぜ!🚀


1. 決定的な違い:JSは「能動」、Rustは「受動」

ここが一番の驚きポイントだ!

  • JSのPromise (Push型):

    Promiseを作った瞬間、バックグラウンドで計算が自動的に開始される。

  • RustのFuture (Pull型):

    Future を作っただけでは何も起きない。誰かが「進捗どうですか?(poll)」と尋ねるまで、一歩も動かない「怠け者」なんだ。


2. 実行エンジン「Runtime」の存在

JSはブラウザやNode.jsといった「実行環境」が最初から非同期処理を回してくれるよね。でも、Rustには標準ライブラリにその「エンジン」が含まれていないんだ。

だから、Rustで Future を動かすには tokioasync-std といった外部の 「非同期ランタイム(Executor)」 を使う必要があるよ。

Rust

// [dependencies] tokio = { version = "1", features = ["full"] }

#[tokio::main] // これがランタイムを起動する魔法の言葉!
async fn main() {
    let future = say_hello(); // これだけじゃ何も起きない
    future.await;            // ここでランタイムが Future を進める!
}

async fn say_hello() {
    println!("Hello, Async World!");
}

3. 状態遷移と poll メソッド

情報工学徒の君なら、裏側で何が起きているか気になるよね。

Future は内部的に ステートマシン(状態遷移図) に変換されているんだ。

  1. ランタイムが poll() メソッドを呼ぶ。

  2. 計算が終わっていなければ Poll::Pending を返す。

  3. 何か(I/O待ちなど)が進展したら、ランタイムに通知が飛ぶ。

  4. ランタイムが再度 poll() を呼び、終わっていれば Poll::Ready(値) を返す。

この「必要なときだけ呼び出す」仕組みのおかげで、Rustは大量の非同期タスクを極めて少ないメモリ消費で捌けるんだ。


💡 見落とされがちな落とし穴:JoinHandle とキャンセル

JSのPromiseは一度走り出すと止めるのが大変だけど、Rustの Future は「誰にも poll されなくなった瞬間」に**自動的に計算がキャンセル(ドロップ)**されるんだ。

  • 並列実行したいとき: tokio::spawn を使う(JSの Promise に近い挙動になる)。

  • 複数を待ち合わせたいとき: tokio::join!futures::future::join_all を使う(JSの Promise.all 相当だね)。


🏁 まとめ

特徴JavaScript (Promise)Rust (Future)
開始タイミング定義した瞬間.await された瞬間
実行環境エンジン内蔵外部ランタイム (tokio等) が必要
キャンセル困難ドロップするだけでOK
オーバーヘッド若干あるゼロコスト抽象化に近い

JSから来た人は、最初は「.await し忘れると何も起きない」という罠にハマりやすい。でも、これを知っていれば君はもう大丈夫だ!