🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
XHR

XHR(別名XMLHttpRequest)はJavaScriptなどのスクリプト言語を使ってサーバーとHTTP通信を行うAPIを指します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

4回答

4645閲覧

JavaScript イベントリスナーの実行タイミングを理解したい

NayuNayu

総合スコア11

XHR

XHR(別名XMLHttpRequest)はJavaScriptなどのスクリプト言語を使ってサーバーとHTTP通信を行うAPIを指します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

1グッド

5クリップ

投稿2021/03/10 12:04

編集2021/03/10 12:06

質問事項

JavaScript初学者です。
addEventListenerにて定義した処理(イベントリスナー)の実行タイミングを理解しようと以下のコードを実行したのですが、実行結果が想定と異なりました。原因はなんでしょうか。。。

該当のソースコード

JavaScript

1document.getElementById("btn").addEventListener("click",function () { 2 var xhr = new XMLHttpRequest(); 3 4 xhr.addEventListener("readystatechange",function () { 5 console.log("readyState:" + xhr.readyState); 6 },false) 7 8 console.log("1.Open前"); 9 xhr.open("GET", "scripts/book.xml"); 10 console.log("2.Open後,Send前"); 11 xhr.send(null); 12 console.log("3.Send後"); 13 14 }, 15 false 16 );

・ボタン押下時にXMLHttpRequestを実行
・XHLHttpRequestのreadystateが変化したタイミングでイベント実行

想定した結果

イベント発火によるイベントリスナーはsetTimeoutのように、WebAPIによってタスクキューに入ってからコールスタックに入ると理解しているので、イベントリスナーは最後に行われると思ってました。

console

11.Open前 22.Open後,Send前 33.Send後 4readyState:1      <=Openの時のイベント処理 5readyState:2 6readyState:3 7readyState:4

実際の結果

実際には、同期処理である「console.log("2.Open後,Send前");」の処理よりも先に、Openによるイベントリスナーが動作しています。

console

11.Open前 2redyState:1      <=Openの時のイベント処理 32.Open後,Send前 43.Send後 5redyState:2 6redyState:3 7redyState:4
Lhankor_Mhy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

イベントリスナはイベントが発行されたときに同期的に実行されます。なので、イベント発行が同期か非同期かを考える必要があります。

ウェブプラットフォームにおけるイベントは、同期的に発行されるように見えるものと非同期的に発行されるように見えるものがあります。MDN にも同期か非同期かはほぼ書いてないと思うので、もし知りたい場合は規格書を読む必要があります。

readystatechangeイベントの場合は、XHR規格の中で「Fire an event named readystatechange ...」と何箇所かで書かれています。この「Fire an event」は同期的に発行するという意味です。しかしながらこのフレーズがあるからといってプログラマから見て必ず同期的というわけでもなく、何らかの非同期なタスクの中で同期的にイベントを発行していればプログラマから見て非同期的です。

例えば toggle イベントは「2. Fire an event named toggle at the details element.」と書かれていますが、このステップ自体は「queue an element task ... that runs the following steps,」の一部なので非同期に見えるわけです。

投稿2021/03/10 14:24

int32_t

総合スコア21679

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NayuNayu

2021/03/11 04:06

> イベントリスナはイベントが発行されたときに同期的に実行されます。 疑問点の本質をついてくれたような回答です。ガラッと理解が変わりました。 つまりは、XHR.open()ではイベントが同期的に発行され、イベントリスナーも同期的に呼ばれた。 XHR.send()ではイベントがなんらかの非同期処理の中で発行され、イベントリスナーはその非同期処理でイベント発行と同期的に呼ばれる(≒結果的にイベントリスナーは非同期的に実行)ということですね。 ということは、setTimeout等とは異なって、タスクキューは使用しないで即時コールスタックに入るイメージなのでしょうか。。。?
int32_t

2021/03/11 04:46

2段落目、3段落目ともその理解でよいと思います。
guest

0

@int32_t さんの高評価回答を打ち消すようですが、私は同期/非同期を考慮する必要はないと考えます。
readystatechange イベントが発動するタイミングを決めるのは、何らかの処理上で readystatechange イベントが発火するからです。

  1. IF[ これ°の状態 ≠ open した ]:

これ°の状態 ← open した
これ°に向けて,名前 readystatechange のイベントを発火する

XMLHttpRequest#open() の処理には「readystatechange イベント発火」が含まれています。

Re: NayuNayu さん

投稿2021/03/11 04:32

think49

総合スコア18189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NayuNayu

2021/03/11 13:46

>readystatechange イベントが発動するタイミングを決めるのは、何らかの処理上でreadystatechange イベントが発火するからです やはり「イベント発火=イベントリスナー実行」ということですね。 その理解の上でリファレンスをみると、確かにと納得できました。 ※リファレンスみると、@FromMZ150 さんの通り実行すると「redyState:2、redyState:3」がコンソールに出ない理由であったりが理解できました @int32_t さんの回答と合わせて、より理解が深まりました。ありがとうございます
guest

0

実行結果が想定と異なった原因は、

同期にしたくて、false をつけた位置が間違っているから。
addEventListener の後ろにつけるのではなく、
xhr.open のところにつけて試してみてください。

投稿2021/03/11 04:05

FromMZ1500

総合スコア496

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NayuNayu

2021/03/11 13:06

同期にしたいわけではなく、イベントリスナーの実行タイミングを知りたいという質問でした。 ただ、OpenにFalseとして同期にしてみるとredyState:2、redyState:3がコンソールに出ないという初めてみる挙動をしたので、楽しめましたありがとうございます。
guest

0

「実際の結果」は特におかしくないです。

【XMLHttpRequest.readyState - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/readyState#example

投稿2021/03/10 13:32

kei344

総合スコア69596

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NayuNayu

2021/03/11 03:52

MDNリファレンスの連携ありがとうございます。 ただ、深堀しすぎかもですが、なぜそうなるのか?が知りたいことでした。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問