NIFCLOUD-mbaas / UserCommunity

ニフクラ mobile backend ユーザーコミュニティ
https://mbaas.nifcloud.com/
82 stars 18 forks source link

Monacaからデータストアの値を取得したい #433

Open shizukun opened 8 years ago

shizukun commented 8 years ago

現在、MonacaとNCMBのサービスを利用してアプリ開発をしようとしています。 「index.html」から新規登録またはログインを行い、 「function.js」に記載している関数を使用して初期化しています。

■初期化処理について 新規登録の場合はデータストアに新規フィールドとしてデータ作成して初期化しています。 ログインの場合はデータストアの値を取得して初期化をしています。

■発生している問題 新規登録時は問題なくデータの作成、登録及び取得が行えているのですが、 ログイン時ではデータストアから値を取得できない状況となっております。

データストアのクラスを作成時に「ncmb」を使用しているのですが、 「index.html」から「function.js」へ引数として渡しているので、同一のものを使用していると思います。 どちらの場合もログイン処理後に行われているため、ユーザが不明(アクセス権限絡み)という事でもないと思います。

ドキュメントに記載されている取得の方法(.fetchAll)を使用した際は、 新規登録・ログイン時問わず、他の方と同様に「Origin is not allowed by Access-Control-Allow-Origin」というエラーが出ます。 ログイン時に同じ変数を引数として渡して、データストアのインスタンスを作成しているので、 問題があるようには思えないのですが、なぜか上手くいきません。

ご存知の方がいらっしゃいましたら、ご教示ください。

「index.html」

    $(function(){
        //mBaaSの初期化
        var application_key="application_key";
        var client_key="client_key";
        var ncmb = new NCMB(application_key,client_key);

        var user = ncmb.User.getCurrentUser();

        //アクセス時ログイン済の場合
        if(user !== null){
            location.href = "gameMain.html";
        }

        //ログイン処理
        $("#LoginForm").on("submit",function(){
            var username = $("#username").val();
            var password = $("#password").val();

            //入力欄が空欄の場合
            if(username===""||password===""){
                navigator.notification.alert("ユーザー名またはパスワードが空欄です",loginERR,"ログイン失敗");
                return false;
            }

            //ログイン処理
            ncmb.User.login(username,password)
            .then(function(){
                //ログイン成功 ゲーム画面へ遷移
                loginInit(ncmb,user);
                location.href = "gameMain.html";
            })
            .catch(function(err){
                //ログイン失敗
                navigator.notification.alert("ユーザー名かパスワードが違います",loginERR,"ログイン失敗");
            });

            //ログイン失敗時の関数
            function loginERR(){}

            return false;
        });
        //新規登録処理
        $("#RegisterForm").on("submit",function(){
            var username = $("#RegisterUsername").val();
            var password = $("#RegisterPassword").val();

            //入力欄が空欄の場合
            if(username===""||password===""){
                navigator.notification.alert("ユーザー名またはパスワードが空欄です",registerERR,"新規登録失敗");
                return false;
            }

            //新規登録
            var user = new ncmb.User({
                userName:username,
                password:password
            });
            //新規登録処理
            user.signUpByAccount()
            .then(function(){
                //新規登録成功 & ログイン処理
                ncmb.User.login(username,password)
                .then(function(){
                    //ログイン成功
                    navigator.notification.alert("ご登録ありがとうございます",registerClear,"新規登録が完了しました");
                })
                .catch(function(){
                    //ログイン失敗
                })
            })
            .catch(function(){
                //新規登録失敗
                navigator.notification.alert("既に使われているIDです。",registerERR,"新規登録失敗");
            });

            //新規登録成功時の関数
            function registerClear(){
                //ゲーム画面へ遷移
                initialize(ncmb,user);
            }

            //新規登録失敗時の関数
            function registerERR(){}

            return false;
        });
    });

「function.js」

//新規登録時の初期化処理 function initialize(ncmb,user){

user = ncmb.User.getCurrentUser();

//データを初期化    
var GameData = ncmb.DataStore("GameData");
var gamedata = new GameData;

var testData1 = 0;
var testData2 = 0;

//アクセスコントロール
var acl = new ncmb.Acl();
acl.setPublicReadAccess(true);
acl.setUserWriteAccess(user,true);

//クラウドに保存するデータを設定
gamedata.set("userName",user.userName)
        .set("td1",testData1 )
        .set("td2",testData2 )
        .set("acl",acl);

//データの保存
gamedata.save()
.then(function(){
    var aaa = gamedata.get("userName");   //この時点ではデータの取得は出来てます。
    window.alert(aaa);                                  //取得したデータの表示
    //保存に成功したらゲーム画面へ遷移
    location.href = "gameMain.html";
});

} //既存ユーザーのログイン時、初期化処理 function loginInit(ncmb,user){

user = ncmb.User.getCurrentUser();

//ゲームデータの読み込み
var GameData = ncmb.DataStore("GameData");
var gamedata = new GameData;

var testData1 = 0;
var testData2 = 0;

//testData1  = gamedata.get("td1");
//testData2 = gamedata.get("td2");

var aaa = gamedata.get("userName");  
window.alert(aaa);                                  //「undefined」と表示される

}

goofmint commented 8 years ago
var aaa = gamedata.get("userName");   //この時点ではデータの取得は出来てます。

ですが、保存したデータではなく、JavaScriptで作成したデータを見ています。

gamedata.save()
  .then(function(g){
    console.log(g);
  });

であれば、 gはデータストアから取得したものになります。

loginInitについてはデータストアから検索していないのが問題化と思います。

GameData.fetch().then(function(gamedata) {
  console.log(gamedata);
});

としてください。ただしくACLがセットされているか、管理画面で確認してみるのが良いかと思います。

shizukun commented 8 years ago

回答ありがとうございます。

initialize() で取得していたデータはデータストアから取ってきていたものではなかったのですね。 ご指摘頂いた通りに

gamedata.save()
  .then(function(g){
    window.alert(g.get("userName"));
  });

とすることでデータストアからデータを取得できました。

loginInit() についてですが、

GameData.fetch().then(function(gamedata){
    window.alert(gamedata.get("userName"));
}).catch(function(err){
    window.alert(err);
});

として、データストアから検索しようとすると 「Origin is not allowed by Access-Control-Allow-Origin」というエラーが出てしまいます。

GameDataクラス内のレコードのACLなのですが、 管理画面で確認した所、 全ての会員には「読込」にのみチェックが入っており、 特定の会員には「更新・削除」にのみチェックが入っている状態です。 (特定の会員に対して「読込」にもチェックを入れた場合も検証済み)

GameDataクラス自体のACLはもともと何も設定していなかったので、 管理画面では何もなかったのですが、 「パーミッション設定」で全ての会員に対して 「読込、検索、更新、作成、削除、フィールド追加」にチェックを入れて作成しました。 その状態でも同様のエラーが発生してます。

また、変数「GameData」の宣言箇所を一か所にまとめ、 index.html内に var GameData = ncmb.DataStore("GameData"); を作成し、 initialize(ncmb,user,GameData); loginInit(ncmb,user,GameData); という形にした際でも、 やはり同様のエラーが発生します。

Monaca/NCMBのチュートリアルとして「ワンタップゲーム」を作成したのですが、 その際に使用しているデータストアは今でも問題なく動いている事を確認しております。 上記アプリを参考にして、もう少し調べてみようと思います。

せっかくご回答下さったのに、解決しなくて申し訳ないです。 何かお気付きの点等ございましたらよろしくお願いします。

goofmint commented 8 years ago

Origin is not allowed by Access-Control-Allow-Origin

のエラーはCORSのエラーなのですが、通常であれば出ないものになります。この原因が分かれば解決するのかなと…

shizukun commented 8 years ago

コメント有難うございます。 少し調べていて疑問に思う点がいくつかあったので共有させて頂きます。

■今回発生している「CORS」のエラーというものは、 データストアへのデータ保存時や、保存直後のアクセスには発生せず、 ログアウト→ログインという過程を挟むことによって発生している点。 ↑ Monaca/NCMB 間の問題であればそもそも保存も出来ないのではと・・・

■MonacaIDEでプロジェクトを作成した後に、プロジェクト名の変更しております。 この時「○○のテンプレート」→「xxx」と名前を変更しているのですが、 ファイル「config.xml」に記載されている「widget name」タグの中身が以前のプロジェクト名のままだったので 同ファイルの name タグの中身だけ変更したという点。 ↑ 正規の手続きであるか不安

■MonacaIDEを開いているブラウザが chrome なのですが、 起動オプション等なにも設定していない。 ↑ ワンタップゲームでは発生していないので関係ないと思われますが。

■MonacaIDE内のwww直下に js フォルダを作成して、 自作した jsファイルなどを入れているのですが、 これらのファイルを index.html 内で読み込んでいます。

<script type="text/javascript" src="js/three.min.js"></script>
<script type="text/javascript" src="js/Detector.js"></script>
<script type="text/javascript" src="js/stats.min.js"></script>
<script src="js/function.js"></script>
<script src="js/ncmb.min.js"></script>

MonacaIDE では「loader.js」が読み取ってくている等の記載もどこかにあったのですが、 読み取ってなさそうなファイルもあったので、すべて記載してます。 ↑ 読み込みが二重になっているのが問題になっている・・・?

■以前作成したワンタップゲームは今年の2月頃なので、 今回作成しているアプリとは ncmb のバージョンが違うのですが、 こちらも関係してくるのでしょうか・・・。

まだ少し調査不足なので、もう暫く調べてみようかと思います。

shizukun commented 8 years ago

検証してみたところ

GameData.fetch().then(function(gamedata) {
  console.log(gamedata);
});
window.alert("まってね");

のようにデータを検索した後に、アラートなどで待機させてみるとうまくデータを取ってくるようになりました。 何故かはわかりません・・・ (非同期通信とか関係してくるのでしょうか・・・)

とりあえず、実装するにあたりちょっと使えない手段だったので、 今回の件ではローカルにデータを保存する方向に切り替えました。

お騒がせして申し訳ありません。 ありがとうございました。