質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
並列処理

複数の計算が同時に実行される手法

JavaScript

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

Q&A

解決済

3回答

2320閲覧

【並列処理】setTimeout()では並列処理にならないのでしょうか?

HelloWorld2

総合スコア32

並列処理

複数の計算が同時に実行される手法

JavaScript

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

0グッド

2クリップ

投稿2019/03/29 10:06

わからないこと

  • setTimeout(func,int ms)を使用すると、「ms秒後にfuncを実行する」処理が、setTimeoutの後続処理と並列で実行されると思っていたのですが、違うのでしょうか?
  • JavaScriptで並列処理を実装するためには、どうすれば良いのでしょうか?(WebWorkerは、並列処理させる処理を別ファイル化する必要があるようなので除外します。※処理はすべてhtml内に記載したいです。)

試したこと

  • 下記コードを実行したところ、hoge()が10秒待った後に実行されました。
  • hogeとsleepが並列で処理される想定でしたが、想定外となりました。

JavaScript

1setTimeout(hoge,0); 2sleep(10000);//別処理の代わり 3 4function sleep(a){ 5 var dt1 = new Date().getTime(); 6 var dt2 = new Date().getTime(); 7 while (dt2 < dt1 + a){ 8 dt2 = new Date().getTime(); 9 } 10 return; 11} 12//並列実行したい処理 13function hoge(){ 14 //処理 15}

よろしくお願いいたします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

JavaScriptはシングルスレッドなので、
完全な並列処理は実現不可能です。
常に実行出来るのはその1行だけ。

イベント駆動という思想を採用しており、
イベント置き場に「イベントの完了条件」と「実行して欲しい関数」をセットで登録します。
その後JavaScriptの全ての処理が完了して暇になったらイベントループという巡回モードに入ります。

イベントループで完了条件を満たしたイベントを発見すると、
そのイベントの関数を取り出して実行します。
関数の実行が完了すると、またイベントループの巡回に戻り完了条件を満たした関数を取り出して実行…というサイクルになります。

超高速に関数をハイ終わり、次!という風に捌いているのがJavaScript流の疑似並列処理であり、
一度に実行している処理は常に1つなのです。

下記コードを実行したところ、hoge()が10秒待った後に実行されました。

今回使われているsleep関数は無限ループのようなもので無理やり処理をせき止めています。
この手法をビジーウェイトと呼びますが、JavaScriptに於いては非推奨です。

イベントループの巡回を始めるにはJavaScriptの現在実行中の処理が全て完了する必要があるので、
ビジーウェイトでせき止めるとhoge関数の発火が遅れ、10秒待たされる事になります。

また、実行中はブラウザの応答も停止するので、
マウスでページをスクロールするといったことも出来なくなってしまいます。
ですので、Ajaxを含め、待たせるとか何時終了するか分からない処理はイベント登録という形で飛ばし、JavaScriptの実行自体は早々に終了させる設計にするべきなのです。


『追記』

・追加する処理は、既存のhtmlの表示や処理を邪魔しないようにする。(今回の質問内容はここです)

・追加処理の内容は、①日時取得 ②Cookie作成 ③別APIへのデータ送信($.post()を用いる)などです。

要望がこれなので、
普通にイベント駆動のやり方で非同期処理書いていけば良いんですよ。

並列でやりたいなら好き勝手に完了条件と実行して欲しい関数をセットでイベント登録すれば良いですし、
直列でやりたいなら、Aの条件が完了をトリガーで発火する関数に、BとCの処理内容を書きましょう。
その場合関数登録がどんどんネストして辛くなってきます。
この関数のネストをコールバック地獄と呼びます。

コールバック地獄の解消方法は色々ありますので、必要になったら別途調べてみてください。

投稿2019/03/29 10:30

編集2019/03/29 10:40
miyabi-sun

総合スコア21158

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

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

HelloWorld2

2019/03/29 10:37

> イベント登録という形で飛ばし イベント登録というのは、どのような処理でしょうか・・・? イメージ的には、「後でこの処理やっといてね」的な感じで、どこかのキューのようなものに入れる感じでしょうか? 仮にイベント発火前にページ遷移したとしても、その登録した処理は確実に実行されるのでしょうか?
miyabi-sun

2019/03/29 10:43

> イメージ的には、「後でこの処理やっといてね」的な感じで、どこかのキューのようなものに入れる感じでしょうか? その理解で合ってます > 仮にイベント発火前にページ遷移したとしても、その登録した処理は確実に実行されるのでしょうか? ページ遷移と同時にJavaScriptの全ての実行を中断し、 定義した変数や登録したイベントなども全て捨ててしまいます。 なのでページ遷移は一切させない。 JavaScriptでページ遷移っぽく表示されてる画面を全リフレッシュしてエミュレートする、 SPA(シングルページアプリケーション)というWebサイトの作り方もあります。
HelloWorld2

2019/03/29 10:45

なるほど、だとすると、イベント登録という形は望ましくないですね。(onloadでやれば済む話な気がするので) 今回Webページの作り的には手を加えられないので、 なんとかJavaScriptで並列処理を実装したいところでしたが、難しそうですね。。。
HelloWorld2

2019/03/29 10:50

追記読みました。 > 普通にイベント駆動のやり方で非同期処理書いていけば良いんですよ。 すみません、初心者なもので、「イベント駆動のやり方」とはどのような記述なのでしょうか・・・?
HelloWorld2

2019/03/29 11:00

setTimeout(hoge,0)のようにすれば良いということですかね? シングルスレッドということなので、setTimeoutの処理が優先されて同期処理になってしまうのでは・・?と思うのですが、間違っておりますでしょうか?
guest

0

setTimeout(func,int ms)を使用すると、「ms秒後にfuncを実行する」処理が、setTimeoutの後続処理と並列で実行されると思っていたのですが、違うのでしょうか?

ふつうはそうなるのですが、JavaScriptはシングルスレッドなので、ここでのsleepのようにビジーループを続けている場合、処理が終わるまでsetTimeoutなど他の処理は実行されません。

JavaScriptで並列処理を実装するためには、どうすれば良いのでしょうか?

えっと、並列に処理されたい内容は、上の例のような「JavaScript上での演算など」ということでしょうか?それとも別な処理でしょうか?

投稿2019/03/29 10:20

maisumakun

総合スコア145121

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

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

HelloWorld2

2019/03/29 10:26 編集

> 並列に処理されたい内容は、上の例のような「JavaScript上での演算など」ということでしょうか? 具体的に言うと、 ・既存のhtmlが存在する。(JavaScriptとか、画像ファイルも含む) ・そのhtmlに新たにJavaScriptの処理を追加する。 ・追加する処理は、既存のhtmlの表示や処理を邪魔しないようにする。(今回の質問内容はここです) ・追加処理の内容は、①日時取得 ②Cookie作成 ③別APIへのデータ送信($.post()を用いる)などです。
maisumakun

2019/03/29 10:28

DOM処理が加わるとなると、ブラウザ上のスレッドでやるしかないので、並列実行は基本的に「無理」です。
HelloWorld2

2019/03/29 10:30

DOMについてよく知らないのですが、ここでは「Cookie作成」がそれにあたるのでしょうか? ちなみに、「WebWorker」を使用しても、実現は不可能なのでしょうか?
maisumakun

2019/03/29 10:33

$.postは問題なく非同期実行されます。
HelloWorld2

2019/03/29 10:39

では、Cookieの生成は同期処理として実装して、他の処理はsetTimeout(hoge,0)としてhoge内に定義すれば、並列で実行されるということでしょうか?
guest

0

sleepがイマイチなにをしたいのか読み取れませんが
普通に非同期処理になっていませんか?

javascript

1setTimeout(hoge,2000,"x"); 2setTimeout(hoge,1000,"y"); 3hoge("z1"); 4hoge("z2"); 5 6function hoge(arg){ 7 console.log(arg); 8}

同期・非同期を調整

javascript

1function wait(sec,txt) { 2 return new Promise((resolve)=>{setTimeout((v)=>{console.log(v);resolve();},sec*1000,txt)}); 3} 4(async()=>{ 5 await wait(2,"a"); 6 wait(4,"b"); 7 await wait(2,"c"); 8 await wait(1,"d"); 9})(); 10

上記であれば、
0. 2秒待ってaを表示
0. そこから並行処理がはじまり、2秒待ってc
0. 1秒待ってd
0. aの4秒後(dの1秒後)にbが出力されます

投稿2019/03/29 10:16

編集2019/03/29 10:59
yambejp

総合スコア114572

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問