質問: ### 前提・実現したいこと RaspberryPi上ののbottleサーバーを使用し、そこにアクセスしたときにJavaScriptでcsvファイルをサーバーから取得し、そのファイル情報を基に処理を行いたい。 ### 発生している問題・エラーメッセージ csvファイルの取得を行ってみたが、XMLHttpRequestが同期読み込みは推奨されていないらしく~~エラー~~警告が出てしまい、代替方法が分からず困っています。 追記:上手く動作しないときがあります。 ``` (index):23 [Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. ``` ### 該当のソースコード ``` CSV読み込みサンプルページ CSV読み込みサンプル 読み込んだCSVが開発コンソールに表示されます。 ``` ``` 太郎,21 二郎,18 三郎,15 ``` ``` #!/usr/bin/env python from bottle import run, route, template, request, static_file @route("/") def test(): return template("sample.html") @route('/static/') def static(file_path): return static_file(file_path, root='.') run(host="0.0.0.0", port=8080) ``` ### 試したこと ソースコードは以下のサイトを参考にしました。 https://joyplot.com/documents/2017/03/01/xmlhttprequest-javascript-csv/
回答: ん〜、この「RaspberryPi上ののbottleサーバ」はインターネット上に広く公開するんですか? ローカルのLAN内で完結してるなら別にそれで良いんじゃね?と思いますがいかがでしょう。 > > 推奨されていないらしくエラーが出てしまい、代替方法が分からず困っています。 > > > エラーじゃなくて警告じゃないんですか? では何故警告が出るか解説していきます。 JavaScriptはシングルスレッドです。 そして(非推奨ですが)document.writeでHTML文字列を無理やり記述してパーサーに解析させる機能が備わっている以上、ブラウザの全ての動作が停止します。 つまり、JavaScriptの実行が終了しなければブラウザがフリーズします。 もし試すなら、下記のJavaScriptを実行してみてください。 見事にブラウザのタブが応答しなくなるはずです。 ``` var i = 0; while (true) { i++; } ``` まぁ、XMLHttpRequestはAjaxと呼ばれる技術であり、 その実態は裏側でHTTPリクエストをWebサーバに飛ばしてレスポンスを受け取るという一連の流れです。 ローカルのLAN内同士の通信ならともかく、南米にあるようなサーバだと軽く1秒掛かったりします。 日本のサーバでも負荷がかかって応答に時間が掛かってるような状態だと普通に2〜3秒待たされることもあります。 この2〜3秒が致命的なんですね。 ボタンクリックやリンクのクリックなど、全ての動作がキャンセルされてまるでフリーズしたかのような挙動になります。 なのでファイルアクセスやネットワークアクセスのような遅くなりがちな処理は、 JavaScriptの管轄内ではやらないよ!イベントループという概念で処理していくよ! ...という思想でやっています。 イベントループの詳細はぐぐっていただくとして、 大雑把に言えばイベント置き場に「イベント達成条件、発火する関数」をセットで登録しておきます。 JavaScriptの処理自体は全て一瞬で終わらせて、ブラウザ内部のイベントループ機能で「達成したイベントないかな?」と探し、達成済みのイベントがあれば1つずつ関数を取り出して動かすという風に解決していきます。 「イベントの達成条件」というのはaddEventListenerで指定出来る他にも山のように存在し、 例えばnミリ秒待ってから実行するようなものも存在します。 ``` // 1000ミリ秒=1秒なので、1秒後にコンソールに表示される setTimeout(function () { console.log('hello world'); }, 1000); ``` > > 代替方法が分からず困っています。 > > > もしJavaScript流儀に従うのであれば非同期でやりましょう。 XMLHttpRequestは大昔のIEがなんかよくわからんけど便利かもしれないから入れておこうと実装した機能です。 2002年にGoogleMapというWebアプリがヒットしてAjaxとして爆発的に普及しましたが、 このXMLHttpRequestが非常にクソな実装であり難解、多くのエンジニアを地獄に叩き落としてきました。 2006年にサードパーティのjQueryライブラリが普及し、エンジニアはAjaxを簡単に実装できるようになりました。 また、2013年頃にはHTML5という仕様でFetch APIが定義され、 IE以外の現行のブラウザの多くはFetch APIをサポートしています。 ローカルで使う予定ならChrome等を使うことになると思うのでFetch APIで実装してみると良いでしょう。 Fetch API - MDN Fetch APIの関数を発火すると、戻り値がPromiseのインスタンスで帰ってきます。 Promise Promiseは次世代の非同期処理の表現手法なので勉強してみてください。