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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Cordova

Cordovaは様々なデバイスで使うことができるオープンソースなモバイル用開発プラットフォームです。開発者に各デバイスの元のプラットフォームで開発する必要をなくし、HTML・JavaScript・CSSなどの一般的なウェブのテクノロジーを使ってすべてのデバイスで展開することができるモバイルのアプリケーションを生成することを可能にします。

JavaScript

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

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

Q&A

解決済

6回答

651閲覧

【JavaScript】処理に前後関係を付けるロジックを組みたい(お知恵をお借りしたい)

Clavat

総合スコア92

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Cordova

Cordovaは様々なデバイスで使うことができるオープンソースなモバイル用開発プラットフォームです。開発者に各デバイスの元のプラットフォームで開発する必要をなくし、HTML・JavaScript・CSSなどの一般的なウェブのテクノロジーを使ってすべてのデバイスで展開することができるモバイルのアプリケーションを生成することを可能にします。

JavaScript

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

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

0グッド

3クリップ

投稿2017/11/13 02:41

編集2017/11/13 03:49

JavaScriptの処理ロジック(ロジックの構築)に
お知恵をお借りしたいと思います。

【実現したいこと】
コード内の①と②に ①⇒②の処理順を設定したい。

ただし、①は実行されるとは限らない。
②は必ず実行されるが、①よりも後に実行され、
①で値がセットされていれば、①の値を使って②を処理したい。

【困っていること】
②は必ず起動しなければいけません。
現状、このコードを実行すると、②⇒①の順で実行されてしまうため、
①⇒②となるように、何らかのロジックを入れて制御したいです。

上記で記載したように ① が実行されるかわからないため、
なんらかの形で②の起動条件を決めないといけないかな、と思っています。

【コードの説明】
これはスマホアプリの挙動を制御するプログラムです。

ons.ready(function() {});
アプリが起動したら必ず実行される内容を記述する部分と思ってください。
(アイコンから起動した場合でも、プッシュ通知から起動した場合でも)

②init(mode)
アプリが起動したら実行される処理が記載されていると思ってください。
(アイコンから起動した場合でも、プッシュ通知から起動した場合でも)

①window.FirebasePlugin.onNotificationOpen
アプリが「プッシュ通知」から開かれた場合のみ実行される部分です。
そのため「アイコン」から起動された場合は実行されません。

 【追記ここから】
なお、①のwindow.FirebasePlugin は Cordova という
アプリ開発環境が前提です(だと思っている)ので
ons.ready の中に置く必要があります。
※外に関数で定義して、ons.readyの中から外の関数を呼ぶでもOKです。

 ②のinit()は ons.readyの外にあっても処理自体は動きますが、
どこかで呼び出し、①⇒②の順でなければなりません・・・。

 【追記ここまで】

<script> ons.ready(function() { var mode = "icon"; //① プッシュ通知から開かれた場合のみ実行される window.FirebasePlugin.onNotificationOpen(function(notification){ mode = "push"; ・・・・ }); //②...初期化処理initをmodeを引数にして起動 init(mode); });// ons.ready()ここまで </script>

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

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

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

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

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

guest

回答6

0

ベストアンサー

なるほど、なんとなく分かりました。
確かに難問ですね。
というのも、この部分が非同期実行されることにあります。

JavaScript

1// ① プッシュ通知から開かれた場合のみ実行される 2window.FirebasePlugin.onNotificationOpen(function(notification){ 3 mode = "push"; 4 // ・・・・ 5});

JavaScriptに於けるonXXXというメソッドは、
「もし○○の条件を満たしたら渡した関数実行してね、じゃ俺は下の行を実行するから〜」
…という作りになっています。

JavaScriptはシングルスレッドで動作するので、
ネットワークやファイルI/Oの操作を待っているとその度にプログラムがプチフリしまくる事になります。
その対策として、非同期処理は待たずにさっさと次の行を実行する設計を選択しています。


質問文との相性が悪い原因は、
1が行われるか行われないか全くわからない状況で2の処理を待つか実行するかを選択しなければならない
…という究極の二択を迫られている事にあります。

  • 一生Push通知クリック判定を待ち続けて初期化処理が行われない
  • Push通知クリック判定を無視してさっさと初期化処理を継続するか

これはどうしようもない問題なので、設計を変えましょう。


Push通知の目的ってそもそもなんですか?

例えばTwitterのアプリだったりした場合、
友達のリプライやリツイートのPush通知をタップします。
そのタップしたリプライやリツイートのページを開きたいのではないでしょうか?

なので、Push通知タップからのinitメソッドを実行することは諦めて、
Push通知タップはあくまでその画面へ遷移する為のトリガーにしましょう。

投稿2017/11/13 05:51

miyabi-sun

総合スコア21158

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

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

Clavat

2017/11/13 06:31 編集

ご回答ありがとうございます。 >これはどうしようもない問題なので、設計を変えましょう。 この部分までのご説明、まさにその通りですごく納得です。 第三者のプラグインなので onNotificationOpen が何をしているか詳細が ブラックボックスではあるのですが、おそらく onXXX だと思います。 -------- プッシュ通知の目的は、お察しの通り、プッシュ通知に含まれるURLを開くことです。 現状のinit処理では、アプリのトップ画面(のURL)を表示するようにまとめてしまっています。 実現したいことは、 プッシュ通知でアプリを開いた場合、プッシュ通知で指定された画面を開く プッシュ通知ではなくアイコンでアプリを開いた場合、トップ画面を開く というものです。 これまでの設計(思想)では、 プッシュ通知で開いたかどうかを初期処理よりも先に判断したい。 プッシュ通知だったらそのURLを保持した状態で、初期処理をしたい! でした。 そうではなく、初期処理は最初に行って終わらせておく。 (プッシュ通知に依存するな、待つな が大原則) ↓ その上でもしプッシュ通知が開かれたのであれば、 開かれたときの処理(表示画面を変える)を実行する(後から実行して、画面を書き換えるとか) というような作りに変更したほう良さそうってことですね。
miyabi-sun

2017/11/13 06:49 編集

エクセレント、その通りです! ああでもでも…他の既製品、例えばTwitterクライアントとかの仕様ですが、 Push通知をタップした時の挙動は、 URLみたいなパラメータを付属してアプリを起動してるんじゃないですか? 質問文開始時点が前提条件、つまり起動後のJS面からのアプローチのみではお手上げですが、 最初のタップ起動か普通にアプリ起動かを、 「付帯パラメータの有無等を使って同期判別出来る」のであれば話は変わってきますね。 私はCordovaの事は詳しくないのですが、 パラメータ付与起動が出来ないか、それを同期で判別出来ないかもう一度調査してみてはどうでしょうか?
Clavat

2017/11/13 06:49

ご回答ありがとうございます。 (認識が間違っている可能性多々ありますが、その辺りは調べておりまして) ネイティブアプリであれば、アプリを開く時点で プッシュ通知のメッセージ(オブジェクトみたいなもの)そのものがあるかを 判断する方法はあるようです。 ただ私が使用している Cordova + プラグイン という環境では、 それに該当しそうなものを見つけられませんでした。 ですので、プッシュ通知をタップして起動する過程においては、 ①アプリが起動する(ons.readyに書いた初期処理が実行される) ↓ ②プッシュ通知を開く(プッシュ通知メッセージ内にURL情報を埋め込んでいるので、それを見る) という方法を取るしかなさそうです。 最初したかったことは「先にプッシュ通知のURLを取得した状態」で「初期処理の続きをしたい」 でした。 既に組んでいる関数の順序や分割・統合など、処理の組み替え等に取り込んでみようと思います!
miyabi-sun

2017/11/13 07:13

そこは予め調査済みだったのですね。 その解決策として捻り出したのが本質問だったわけですね。 承知しました、残りの処理頑張ってください。
guest

0

kei344 さんのコメント欄のアドバイスで解決可能と考えていたので、この展開は意外でした。

同期処理

ただし、①は実行されるとは限らない。
②は必ず実行されるが、①よりも後に実行され、
①で値がセットされていれば、①の値を使って②を処理したい。

同期処理でこの課題を解決するのは簡単です。

JavaScript

1'use strict'; 2var foo = { 3 a: 0, 4 process1: function process1 () { 5 this.a = 1; 6 console.log('①'); 7 }, 8 process2: function process2 () { 9 console.log('②', this.a); 10 } 11} 12 13var bar = 1; 14 15if (bar) { 16 foo.process1(); 17} 18foo.process2();

しかしながら、ons.ready, window.FirebasePlugin.onNotificationOpenイベント駆動なので、使用しているライブラリ/DOMの「イベントモデル」のルール内で対応するハンドラ関数が発火します。

イベントモデル

kei344 さんが紹介して下さったURLからリンクを辿ると、イベントの発火順に触れた記事が見つかります。

Google先生に尋ねればpluginが利用可能になるタイミングが deviceready イベントである事が分かるので、次のように書きます。

JavaScript

1document.addEventListener("deviceready", function handleDeviceReady (event) { 2 console.log(event.type); // "deviceready" 3 4 window.FirebasePlugin.onNotificationOpen(function(notification){ 5 console.log('notificationOpen'); 6 }); 7}, false); 8 9ons.ready(function() { 10 console.log('ons.ready: Onsen UI load complete'); 11});

このコードで「deviceready -> ons.ready」の順番で発火する事は保証されているので、「onNotificationOpen と ons.ready のどちらが先に発火するイベントモデルなのか」が問題ですが、検証すればすぐに結果は出るでしょう。
(考えづらいと思いますが、もし、ons.ready が先に発火するのであれば、onNotificationOpen が発火するまで数秒間待機させるか、別のイベントを探す必要があります。)

NotificationOpen イベント

  1. App is in foreground:

i. User receives the notification data in the JavaScript callback without any notification on the device itself (this is the normal behaviour of push notifications, it is up to you, the developer, to notify the user)
2. App is in background:
i. User receives the notification message in its device notification bar
ii. User taps the notification and the app opens
iii. User receives the notification data in the JavaScript callback

NotificationOpen イベントはバックグラウンド実行されたアプリから復帰した時にも発火するイベントです。
従って、先のコードで処理を行うと既に初期化処理が終わっているアプリに対して、バックグラウンドから復帰時にもう一度初期化処理が走る事になります。
それが望まない動作であるなら、フラグ管理する等して初期化済かどうかを判断する条件分岐処理が必要になります。
ちなみに、Monaca には resume イベントが用意されているようです。

Re: Clavat さん

投稿2017/11/13 08:16

編集2017/11/13 08:54
think49

総合スコア18162

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

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

Clavat

2017/11/13 09:37

ご回答ありがとうございます。 Monaca関連で質問していたのですが、回答が付かなかったため、 出来るだけ多くの方からアドバイスが頂けたらと思い、 MonacaやCordovaの説明部分(共有したいこと)をそぎ落とし、 JavaScriptの部分だけにして質問しなおしたのですが、 それが逆に話をややこしくしてしまいました・・・。 申し訳ございません。 まず質問記載時点で kei344さん、think49さん が教えてくださった イベント発火順といいますか、pluginが利用可能になるタイミングが Cordovaのdeviceready イベントであること、 ons.ready がCordovaの準備完了も内包する(表現が正しくないかもです)ことは 理解していたつもりです。 個人的に理解が弱かった部分として(現時点の認識として)は、 onNotificationOpen が非同期処理というところで (「もし○○の条件を満たしたら渡した関数実行してね、じゃ俺は下の行を実行するから〜」) miyabi-sunさん、yambejpさんが回答してくださった通り、 実行されるかわからないものを先行にして、 必ず実行されるものを後続に付けようとしていたのが、そもそも間違いだから、 ロジックの組み立てが間違いなんだな、という理解です。 私自身、あまりJavaScriptに精通していないこともありますが、 現時点で「論理矛盾」だと思っています。 もし「こう書いたらすぐに解決出来るだろうに・・・」という意味でご回答いただいていましたら、 私の中で皆様の頭の中にあるコードが浮かんでいないのだと思います。 そういう意味で、think49さんがご指摘の ①kei344 さんのコメント欄のアドバイスで解決可能 ②この展開 が何を指されているか、すみませんが理解が及んでいません。 こう書いたらいいのでは? というサンプルコードがあれば「なるほど!」と 理解できるような気がしていますが、お恥ずかしいですが、 ① ⇒ どう書けば解決するの? ② ⇒ 考え直さなくてもいいの? という状況ですので、 初期処理は最初に行って終わらせておく。 (プッシュ通知に依存するな、待つな が大原則) ↓ その上でもしプッシュ通知が開かれたのであれば、 開かれたときの処理(表示画面を変える)を実行する(後から実行して、画面を書き換えるとか) というような作りに変更 しようとコードの見直しを進めている状況です。
Clavat

2017/11/13 09:42

追伸 NotificationOpen イベントはバックグラウンド実行されたアプリから復帰した時にも発火するイベントです。従って、先のコードで処理を行うと既に初期化処理が終わっているアプリに対して、バックグラウンドから復帰時にもう一度初期化処理が走る事になります。 ⇒はい、プッシュ通知起動による復帰でも「初期化処理が走る」で、今のところ問題ありません。
guest

0

Onsen UI はよくわかりませんが、window.FirebasePluginons のコード内で定義されていないなら、下記のような方法で出来ると思います。

JavaScript

1 var mode = "icon"; 2 //① プッシュ通知から開かれた場合のみ実行される 3 window.FirebasePlugin.onNotificationOpen(function(notification){ 4 mode = "push"; 5 ・・・・ 6 }); 7 ons.ready(function() { 8 //②...初期化処理initをmodeを引数にして起動 9 init(mode); 10 });// ons.ready()ここまで

投稿2017/11/13 03:14

kei344

総合スコア69400

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

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

Clavat

2017/11/13 03:45

ご回答ありがとうございます。 前提条件の記載が出来ておらず、申し訳ございません。 window.FirebasePlugin は Cordova というアプリ開発環境が前提です(だと思っている)ので ons.ready の中に置く必要があります。 ※関数で定義して、ons.readyの中から外の関数を呼ぶでもOKです。 init()は ons.readyの外にあっても構いません。
kei344

2017/11/13 03:48

FirebasePluginがons内で定義されているかのみが問題なのですが。
kei344

2017/11/13 03:54

ons.ready の外側で console.log(window);でFirebasePluginがそこに入っているか確認してみては。
Clavat

2017/11/13 03:58

すみません。何が問題なのかがちょっと理解できていないのですが、 FirebasePlugin は Cordova というアプリ開発環境の上で動くプラグインです。 Cordovaが準備できていないと動きません。 ons.ready()が実行されるタイミング=Cordovaが準備できた後になりますので、 ons.readyより先に FirebasePlugin を呼び出そうとするとエラーになります。 ですので、ons.ready内で FirebasePlugin の onNotificationOpen メソッドをまず実行して、 その結果を受けて・・・というように実行したいです。 ご質問の補足になっていますでしょうか?
Clavat

2017/11/13 03:59

ご回答と前後してしまいました、試してみます。
Clavat

2017/11/13 05:02

>ons.ready の外側で console.log(window);でFirebasePluginがそこに入っているか。 入っていないようです・・・。 入っていないから ??? の状態で せっかくのご回答の意図・原因を理解できていなくて申し訳ありません。 別の回答にもレスしましたが、 ①が実行されるときでも、現状、 var mode = "icon"; ⇒  ②init(mode); ⇒ ①mode = "push"; という順番で稼働してしまうので、なんとか①⇒②に出来ないか、という意図です。 現状②⇒①の順になってしまうので、②の処理を後から①で書き換えるしか方法がないのかな、 というところでの悩み(良いロジックがないのか)です。 もう少し考えてみます。アドバイスありがとうございます。
Clavat

2017/11/13 05:56

回答ありがとうございます。 フックの方法(やりかた)を含めて考えてみます。
guest

0

おそらくkei344さんが正しい解説をつけてくれているようなので
ロジックの話だけ

コード内の①と②に ①⇒②の処理順を設定したい。

ただし、①は実行されるとは限らない。
②は必ず実行されるが、①よりも後に実行され、
①で値がセットされていれば、①の値を使って②を処理したい。

論理的に矛盾しているように見受けられます

「②は必ず実行されるが、①よりも後に実行される」ということは
②は①に依存しているということです。

さらに「①は実行されるとは限らない」わけですから
それに付随して「②は実行されるとは限らない」状態です

その状態で「②は必ず実行される」となっているので、条件があいません。

流れとしては

  • ①が実行されたら②は実行される

は確定だとして

  • ①が実行されなかったら②は実行されない
  • ①が実行されない場合でも②は実行されるが他のなにかトリガーが定義されている

のどちらかを定義する必要があります

投稿2017/11/13 04:42

yambejp

総合スコア114784

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

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

Clavat

2017/11/13 04:54

説明が悪く申し訳ありません。 ①が実行されないときは var mode = "icon"; ⇒ ②init(mode); でOKです。 ①が実行されるときでも、現状、 var mode = "icon"; ⇒  ②init(mode); ⇒ ①mode = "push"; という順番で稼働してしまうので、なんとか①⇒②に出来ないか、という意図です。
yambejp

2017/11/13 05:03

まさに前回書いた、どちらかの定義をしていないからでは? ①が実行されるのを待たないで②が実行されるなら、 別のトリガー③あるということですよね? その際①→②を保証したいのであれば ③を発行するときに①が実行されないことをチェックする仕組みを組むことです そうでないかぎり②は①を待ち続けるか、①を無視するかのどちらかでしょう
Clavat

2017/11/13 05:20

そうですね。ロジックとしては理解できました。 Cordovaという開発環境でいうと、 Cordovaが準備できたら(≒アプリが起動したら)実行する処理を ons.ready(function() {}); に記載しないといけないので、 ②init(mode); の実行トリガー③はそもそも ons.ready(function() {}); になる理解です。 そう考えると①の実行トリガー③も ons.ready(function() {}); ということになりそうですが、 ①⇒②で動いてくれていないので  ※ブラックボックスである関数 window.FirebasePlugin.onNotificationOpen が   プッシュ通知メッセージのオブジェクト notification があるとき   (プッシュ通知を開いたときに対して)のみ動いていて、   notification がないときは実行されていない感じです。 これには別のトリガー④がある(③と④の両方がトリガー?)ということになってしまいますよね。 (中に何を書いてもプッシュ通知を開いたときでないと実行されていない状況です) ありがとうございます、もう少し処理の起動条件がうまく書けないか、 別のフラグや、処理を組み替える等、試してみます。
guest

0

プラグインを知らない、回答を全て読んでいませんが…

promiseを使って、非同期処理にすればよいのではないでしょうか?

投稿2017/11/14 00:23

fe.ktym

総合スコア17

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

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

Clavat

2017/11/14 00:30

ご回答ありがとうございます。 事前に試しておりましたが、 window.FirebasePlugin.onNotificationOpen が「プッシュ通知を開いたとき」に 実行されるもので、「アイコンから起動したとき」は実行されないので、 initの先行条件として定義できない  と理解しております。
fe.ktym

2017/11/14 00:55

理解できました。 もしかしたらと思い、よく読まずにコメントしてしまいました。 私も勉強になりました。ありがとうございました。
guest

0

皆さんご回答ありがとうございます。
お三方みなさんから、何がダメなのかをご教授いただきました。
皆さんにベストアンサーを付けたいところですが、1名だけということですので、
こちらの知識レベルとやりたいことに寄り添っていただき、
わかりやすいお答えをいただいたmiyabi-sanとさせていただきました。

投稿2017/11/13 07:01

Clavat

総合スコア92

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問