1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

駆け出しだった頃の話を供養します。
JavaScript(Vue.js)を業務で使い始めて、
きっかり1年ぐらい経とうとしてた目駆け出しエンジニアでそた。
私が担当している某製品のUIはWebの操作に対応していて、とても評判がいいのですが、
ふとネットワークを確認すると定期受信がなんかうまく行ってない。
しかもページによってポーリング間隔がバラバラ…。なんで???

結論

結論から書くとsetTimeout…というよりもJavaScriptの非同期処理の理解不足が原因でした。
APIに対して1秒間隔でRequestを出していくシステムを想定してください。
想像していた処理
SingleThread.drawio.png
詳しい人から見ると一瞬で否定されそうな図ですが、割と本気でこう考えていて、
Fetchさえ1秒以内に間に合えば、常に1秒で実行されるかと思っていました…。
実際の処理
SingleThread_real.drawio.png
超絶当たり前なのですが、 DOMの操作のためにJavaScriptを使用するので
大雑把ですが、こんな感じの図になるはずです。
こうなると、Renderの時間が長すぎて1秒間隔でリクエストを送ることができません。
…なるほど。ん?

JavaScriptってシングルスレッド処理なの?

非同期処理が可能なシングルスレッド処理

ここからは下記が一番私には理解しやすかったですが、もっと噛み砕いて解説していきます。
mercari engineering - JavaScriptがブラウザでどのように動くのか

Javascriptはシングルスレッドで非同期処理をするためにAPIを使用します。
APIとは一般的にはYouTubeやXの情報を取得するやつですが、JavaScript内部でも存在します。

ブラウザー API はウェブブラウザーに組み込まれていて、ブラウザーやコンピューターの環境の情報を取得し、これを使って役に立つ複雑なことを行えるようにするものです。 例えば ウェブオーディオ API は、ブラウザー内での音声の操作、たとえば音声トラックの取得、音量の変更、エフェクトの適用などを行うための JavaScript の仕組みを提供します。実際には、裏でブラウザーは低レベル(例えば C++ や Rust)の複雑なコードを使って実際の音声処理を行います。しかし、この複雑さを API が抽象化して隠蔽します。

PythonでもCPythonなるものがあるようにコンパイラ標準のインターフェースが搭載されております。
JavaScriptの非同期処理は一旦、メインのランタイムとは切り離して処理されます。
ここで以下の例で考えてみましょう。

function main(){
   request();
   fetch();
   render();
}
// 一秒ずつmain関数を3回実行
main();                 // main(1)
setTimeout(main, 1000); // main(2)
setTimeout(main, 2000); // main(3)![ppt73A2.pptm  -  自動回復済み.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690326/164864b7-3cf9-4bc4-b756-a061946025b3.gif)

この場合、図で示すとこのような状態が表せます。
ppt73A2.pptm  -  自動回復済み.gif

ブラウザAPIについて

先程説明の重複ですが、ブラウザ標準に搭載されているAPIです。
今回の場合はsetTimeoutを実現するために使用しています。
ブラウザAPIにmain(2)main(3)をそれぞれ1秒後、2秒後にタスクキューに格納します。

タスクキューについて

タスクキューは FIFO (First In, First Out) 方式で、格納した順に取り出しが行なわれます。
コールスタックキューが空になったらコールスタックで処理を実行します。

コールスタックについて

コールスタックは実際に処理をする場所になります。
この場合はmain(1)main(2)main(3)関数を実行しています。

結局何が起こってたの?

コールスタックが1秒以上も占有されていたorz

イベントループ

上記の画像のように、ブラウザAPIから投げられた関数の処理をキューして処理をしています。ざっくり言えば、このようにシングルスレッドでブラウザ内の各領域を関数がループしていることを イベントループ と呼びます。イベントループで大事なのは、コールスタックが空にならないと次の処理が実行できないことです。

まとめ

今回の場合、常に一定間隔でポーリングをしているつもりが、コールスタックに阻まれて中々、実行できなかったのが原因でした。こうして書いてみるとごく当たり前の話なのですが、駆け出しの頃はJavaScriptをよく知らずVue.jsを使用していたため、非同期処理をあまり意識できず凄く困惑しました。やはりフレームワークを扱うのは初心者にはうってつけですが、こうした落とし穴にハマってしまいやすいですね・・・。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?