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

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

新規登録して質問してみよう
ただいま回答率
85.48%
イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

JavaScript

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

非同期処理

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

Q&A

解決済

2回答

286閲覧

JavaScriptで、複数のイベントから受け渡されるデータが条件を満たしているときに特定の処理を実行させたい

kttl

総合スコア7

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

JavaScript

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

非同期処理

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

0グッド

3クリップ

投稿2018/05/06 10:17

JavaScriptで、複数のイベントから受け渡されるデータが条件を満たしているときに特定の処理を実行させたい

JavaScriptのイベント処理(非同期)で悩んでいます。
通信のためのライブラリで、複数のon('...')イベントに対してそれぞれ関数を設定しています。
関数では受け取ったデータが一定の条件をみたしているかをチェックしています。

javascript

1// バイナリデータを受け取ったときに発火 2dataConnection.on('data', (data)=>{ 3 // 特定のdataを受け取るという条件A 4}); 5 6// メディアストリームを受け取ったときに発火 7mediaConnection.on('stream', (stream)=>{ 8 // streamを受け取るという条件B 9});

このような場合で、AとBの条件を両方満たした場合に、特定の処理をさせたいのですが、どうすれば実現できるでしょうか。
(Primiseやasyncみたいな仕組みで対応できるのでしょうか...?)

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

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

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

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

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

Lhankor_Mhy

2018/05/06 10:50

.on() はどういったオブジェクトのメソッドですか? jQuery でしょうか。
kttl

2018/05/06 10:53

通信のために使っているライブラリ(SkyWay)ですね。EventEmitterを使って実装されているようです。
Lhankor_Mhy

2018/05/06 10:56

では、そのライブラリのドキュメントがないと回答しようがないと思うのですが、いかがでしょうか。
Lhankor_Mhy

2018/05/06 11:30

すみません、ドキュメント見つけられました。ソースコード読んだ感じ、普通に EventEmitter ですね......
Lhankor_Mhy

2018/05/06 11:33

普通に、ラップしてpromise返すか、emitメソッドを上書きしてpromise返すか、ぐらいしかなさそうな気がしました。他の回答者を待ちたい。
karamarimo

2018/05/06 13:31

data と stream は別々のタイミングで来るわけですが、「AとBを両方満たすとき」というのはどういうタイミングなのでしょうか。
kttl

2018/05/07 10:24

質問中の擬似コードのコメント部分にif(A)のような条件文があり、AとBの条件文がどちらもtrueとなり、実行された状態です。
guest

回答2

0

ベストアンサー

Primiseやasyncみたいな仕組みで対応できるのでしょうか...?

可能ですが、依存元のライブラリがPromiseインスタンスを投げ返してくれる前提です。

一応解説しておくと、Promise.allというメソッドが用意されており、
Promiseインスタンスの配列を投げ込むと
全て実行完了になった時に.thenが発火する仕組みになっています。

JavaScript

1const func1 = () => new Promise((resolve, reject) => resolve(123)) 2const func2 = () => new Promise((resolve, reject) => resolve(234)) 3 4Promise.all([func1(), func2()]) 5 .then(results => { 6 console.log(results) // [123, 234] 7 })

該当の処理がPromiseを返さない場合は無理です。
まぁ、Promiseで包んでやれば動くんじゃないですかね?

JavaScript

1const getData = () => new Promise((resolve, reject) => { 2 // バイナリデータを受け取ったときに発火 3 dataConnection.on('data', (data)=>{ 4 // 特定のdataを受け取るという条件A 5 resolve(data); 6 }); 7}); 8 9const getMedia = () => new Promise((resolve, reject) => { 10 // メディアストリームを受け取ったときに発火 11 mediaConnection.on('stream', (stream)=>{ 12 // streamを受け取るという条件B 13 resolve(stream); 14 }); 15}) 16 17Promise.all([getData(), getMedia()]) 18 .then(([data, media]) => { 19 console.log(data); 20 console.log(media); 21 });

ES2017のasync/await構文はPromiseのthenがダサいということで糖衣構文で表現しているだけなので、
Promiseを返さないライブラリ相手では使えません。

やってる事は似たようなもんです。

JavaScript

1const getData = () => new Promise((resolve, reject) => { 2 // バイナリデータを受け取ったときに発火 3 dataConnection.on('data', (data)=>{ 4 // 特定のdataを受け取るという条件A 5 resolve(data); 6 }); 7}); 8 9const getMedia = () => new Promise((resolve, reject) => { 10 // メディアストリームを受け取ったときに発火 11 mediaConnection.on('stream', (stream)=>{ 12 // streamを受け取るという条件B 13 resolve(stream); 14 }); 15}) 16 17// await構文を使うには、async関数内である条件があるので、即時実行関数で発火 18(async functon () { 19 const promises = { 20 data: getData(), 21 media: getMedia(), 22 }; 23 const data = await promises.data; 24 const stream = await promises.media; 25 console.log(data); 26 console.log(stream); 27})();

asyncライブラリ(ES2017のasync/await構文とは別) を利用する手もあります。
リンクを張っておいたので使い方は見て下さい。

ただし、基本的に非同期関数はtry〜catchで握れない為、
第一引数がerrであるという前提で考える慣習があります。

その辺が許容出来るならasyncライブラリは中々良い選択肢だと思います。

投稿2018/05/06 10:57

miyabi-sun

総合スコア21158

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

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

kttl

2018/05/06 11:33

丁寧な回答ありがとうございます。 イベントハンドラの登録ごとPromiseで包んでしまうという方法ですね。 Promise.allでまとめて登録&条件監視する場合はできそうですが、 イベントハンドラの登録のタイミングも別々、という場合にはどうすればよいでしょうか。
miyabi-sun

2018/05/06 13:30

Promiseのインスタンスを作った後、中の処理はこっそり実行中です。 Promiseの状態はインスタンス作成直後はPendingで、resovle・rejectメソッドの実行と共に成功・失敗に状態が切り替わります。 Promise.allが引数として要求する配列は、状態が完了のPromiseが混ざっていても構いません。 作れるPromiseは順次生成して何処かの変数に保存しましょう。 Promise.allは全てのイベントハンドラが出揃ってから、 引数に退避しておいたPromise達で配列を作って投げ込めば大丈夫です。
kttl

2018/05/07 10:20

丁寧にありがとうございました
kttl

2018/05/07 10:30

確かに全体の構造としてはそうするのがよいですね。 ご教授いただきありがとうございます。
guest

0

単にイベントごとに条件が合致するかどうかのフラグを持たせて、最終的なイベントが起こった時にそのフラグをチェックして起動させる、というのでいいかと

投稿2018/05/06 14:06

y_waiwai

総合スコア87774

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

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

kttl

2018/05/07 10:29

回答ありがとうございます。 イベントの発生順番が不定なので、すべてのイベントにその他のイベントが発生したかのチェックとイベント発生したことを登録するという方法で実装していました。 しかし管理が大変なので、よりスマートな方法で実装できないか質問させていただいた次第です。 やはりシンプルにそう実装するのがよいのかもしれません。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問