- jQueryは非同期処理を「簡単にした」のではなく「難しさを隠した」
- 非同期処理が難しい本当の理由
- XMLHttpRequest時代の地獄
- jQueryが行った3つの隠蔽
- なぜ簡単に感じたのか
- 実際に起きていたこと(イベントループ)
- 注意点:理解しないまま使うと必ず壊れる
- 現在のasync/awaitとの関係
- まとめ
jQueryは非同期処理を「簡単にした」のではなく「難しさを隠した」
結論から書きます。
jQueryは非同期処理を単純化したわけではありません。
非同期処理の複雑さを、開発者の視界から見えなくしただけです。
つまり、
- JavaScriptが簡単になった
ではなく
- JavaScriptの難しい部分をjQueryが肩代わりした
これが実態です。
そのため、jQueryを使っていた人が素のJavaScript(Promise / async/await)へ移行すると急に難しく感じます。
難しくなったのではなく、今まで見えていなかったものが見えるようになっただけです。
非同期処理が難しい本当の理由
プログラムの基本は「上から順に実行」です。
console.log("A"); console.log("B"); console.log("C");
これは必ず A → B → C の順で出ます。
これが同期処理です。
しかし通信は待ち時間が発生します。
fetch("/api"); console.log("A");
通信が終わる前にAが表示されます。
これが非同期です。
つまり非同期の本質は、
実行順序がプログラムの順番と一致しない
ことです。
ここから問題が始まります。
XMLHttpRequest時代の地獄
昔のコードを見てみます。
var xhr = new XMLHttpRequest(); xhr.open("GET","/user",true); xhr.onreadystatechange = function(){ if(xhr.readyState===4 && xhr.status===200){ var user = JSON.parse(xhr.responseText); console.log(user.name); } }; xhr.send(); console.log("終了");
出力はこうなります。
終了
(数秒後)ユーザー名
プログラムの下に書いた処理が先に動きます。
初心者が最初に混乱するポイントです。
さらに、複数通信になると一気に破綻します。
getUser(); getPosts(); getComments();
どの順で返るか保証がありません。
UIが壊れる原因になります。
jQueryが行った3つの隠蔽
jQueryはこの問題を3段階で隠しました。
1. コールバックの統一**
$.ajax({ success: function(data){ console.log(data); } });
開発者は「ここに書けば後で実行される」とだけ覚えればよくなりました。
イベントや状態管理を意識する必要がなくなりました。
2. 状態の分離**
jQueryは通信状態を3つに整理しました。
- success(成功)
- error(失敗)
- complete(終了)
XMLHttpRequestではreadyStateとstatusの組み合わせを自分で判定していました。
それをjQueryが分類しました。
3. Deferredによるチェーン化**
$.ajax("/user") .done(function(u){ return $.ajax("/posts?id="+u.id); }) .done(function(p){ console.log(p); });
これにより「順番に処理する」書き方が復活しました。
非同期なのに同期のように書ける、これが最大のポイントです。
なぜ簡単に感じたのか
人間が理解しやすいプログラムは「流れ」があるものです。
しかし非同期は流れを壊します。
jQueryは「流れがあるように見せる」ことで理解を助けました。
内部ではこうなっています。
- イベントキューに登録
- 通信完了でコールバック実行
- Deferredが次の処理を起動
つまり裏では非同期のままです。
表面だけ同期風になっています。
実際に起きていたこと(イベントループ)
ブラウザはイベントループで動いています。
1. JavaScriptを実行
2. キューを確認
3. コールバックを実行
4. 繰り返し
jQueryは、通信完了時にコールバックをキューへ入れます。
開発者はそれを「順番に動いた」と認識します。
つまりjQueryは非同期を消したのではありません。
イベントループを意識しなくてよくしたのです。
注意点:理解しないまま使うと必ず壊れる
典型的な間違いです。
var user; $.ajax("/user").done(function(u){ user = u; }); console.log(user);
これはundefinedになります。
通信前にconsole.logが実行されるからです。
jQueryを長く使っていた人ほど、このバグに遭遇します。
「非同期を忘れて書ける」ことの副作用です。
現在のasync/awaitとの関係
現在は次のように書けます。
const res = await fetch("/user"); const user = await res.json(); console.log(user);
これはjQueryと似ています。
しかし重要な違いがあります。
async/awaitは非同期を隠していません。
「待っている」ことを明示しています。
jQueryは隠し、
async/awaitは表現しています。
まとめ
jQueryが普及した理由は、非同期処理を簡単にしたからではありません。
非同期処理を「理解しなくても使える形」にしたからです。
それは多くのWebアプリを生みましたが、同時に非同期の本質を見えなくしました。
現在のJavaScriptが難しく感じるとき、
それは仕様が複雑になったのではありません。
本来の姿に近づいたとも言えます。
jQueryは問題を消したのではなく、
問題を感じさせない優れたインターフェースだった、ということです。