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

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

新規登録して質問してみよう
ただいま回答率
85.35%
ニフティクラウドmobile backend

ニフティクラウドmobile backend (mBaaS)はニフティが提供するBaasサービスです。プッシュ通知、データストア、ファイルストア、会員管理・認証機能などのバックエンド機能をクラウドから提供しています。 Andoird/iOS/JavaScript/Unityと各種SDKに対応しています。

Monaca

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

Q&A

解決済

3回答

4393閲覧

mBaaSとPusherを使ったチャットアプリで、チャットの内容がすぐに反映されない

T_Furuta

総合スコア25

ニフティクラウドmobile backend

ニフティクラウドmobile backend (mBaaS)はニフティが提供するBaasサービスです。プッシュ通知、データストア、ファイルストア、会員管理・認証機能などのバックエンド機能をクラウドから提供しています。 Andoird/iOS/JavaScript/Unityと各種SDKに対応しています。

Monaca

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

0グッド

0クリップ

投稿2020/03/16 07:44

Monaca,ncmb,pusherを用いてmBaaSとPusherを使ってチャットアプリを作るを読み進めながらチャットアプリを作っています。
サンプルコード通りにやってみたのですが、チャットの内容が画面に反映されません。
メッセージを入力して、送信ボタンを押した後、一度ログイン画面に戻ってから再度ログインしなおすと、先程入力したメッセージが表示されます。

index.html

html

1<!DOCTYPE HTML> 2<html> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"> 6 <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'"> 7 <script src="components/loader.js"></script> 8 <script src="lib/onsenui/js/onsenui.min.js"></script> 9 10 <link rel="stylesheet" href="components/loader.css"> 11 <link rel="stylesheet" href="lib/onsenui/css/onsenui.css"> 12 <link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css"> 13 <link rel="stylesheet" href="css/style.css"> 14 <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> 15 <script src="https://js.pusher.com/5.1/pusher.min.js"></script> 16 <script src="js/app.js"></script> 17</head> 18<body> 19 <ons-navigator swipeable id="nav" page="login.html"></ons-navigator> 20 <template id="login.html"> 21 <ons-page id="login"> 22 <div class="join-area" style="text-align: center; margin-top: 30px;"> 23 <h4>チャットルームにログインしてください</h4> 24 <p> 25 <ons-input id="userName" modifier="underbar" placeholder="ユーザ名" float></ons-input><br /> 26 <ons-input id="chatId" modifier="underbar" placeholder="chatId" float></ons-input> 27 </p> 28 <p style="margin-top: 30px;"> 29 <ons-button onclick="join()">Join</ons-button> 30 </p> 31 </div> 32 </ons-page> 33 </template> 34</body> 35</html>

chat.html

html

1<ons-page id="chat"> 2 <ons-toolbar> 3 <div class="left"><ons-back-button>Back</ons-back-button></div> 4 <div class="center"></div> 5 </ons-toolbar> 6 <input type="hidden" id="channelId" /> 7 <div class="chat-area"> 8 <ons-list id="chats"></ons-list> 9 </div> 10 <div class="send-area"> 11 <ons-input id="message" placeholder="メッセージ"></ons-input> 12 <ons-button onclick="send()" modifier="quiet">送信</ons-button> 13 </div> 14</ons-page>

app.js

javascript

1 2// This is a JavaScript file 3let pusher; 4let ncmb; 5const app_id = 'MY_PUSHER_APP_ID'; 6const app_cluster = 'MY_PUSHER_CLUSTER'; 7const applicationKey = 'MY_NCMB_APPLICATION_KEY'; 8const clientKey = 'MY_NCMB_CLIENT_KEY'; 9 10// グローバル変数の処理 11ons.ready(function() { 12 pusher = new Pusher(app_id, { 13 cluster: app_cluster, 14 forceTLS: true 15 }); 16 ncmb = new NCMB(applicationKey, clientKey); 17}); 18 19// 初期表示処理 20$(document).on('init', (event) => { 21 if (event.target.id === 'login') { 22 $('#chatId').val('channel'); 23 const userName = localStorage.getItem('userName'); 24 if (userName) 25 $('#userName').val(userName); 26 } 27}); 28 29// チャット画面を表示したときの処理 30$(document).on('show', (event) => { 31 if (event.target.id === 'chat') { 32 const data = event.target.data; 33 $('#channelId').val(data.chatId); 34 connectPusher(data.userName, data.chatId); 35 loadChat(data.userName, data.chatId); 36 } 37}); 38 39// チャット画面から戻った時の処理 40$(document).on('hide', (event) => { 41 if (event.target.id === 'chat') { 42 pusher.unsubscribe($('#channelId').val()); 43 } 44}); 45 46// チャットルームにログインする処理 47const join = () => { 48 const userName = $('#userName').val(); 49 if (userName === '') { 50 ons.notification 51 .alert('ユーザ名を決めてください'); 52 return; 53 } 54 localStorage.setItem('userName', userName); 55 const chatId = $('#chatId').val(); 56 $('#nav')[0].pushPage('chat.html', { 57 data: { userName, chatId } 58 }) 59} 60 61// Pusherに接続する処理 62const connectPusher = (userName, chatId) => { 63 const channel = pusher.subscribe(chatId); 64 channel.bind('message', function(data) { 65 showChat(userName, data); 66 }); 67}; 68 69// 既存のチャットメッセージを読み込む処理 70const loadChat = (userName, channel) => { 71 const Chat = ncmb.DataStore('Chat'); 72 Chat 73 .equalTo('channel', channel) 74 .fetchAll() 75 .then(chats => { 76 for (let chat of chats) { 77 showChat(userName, chat); 78 } 79 }); 80} 81 82// メッセージを一つ表示する処理 83const showChat = (userName, data) => { 84 if (data.userName == userName) { 85 $('#chats').append(` 86 <ons-list-item modifier="nodivider"> 87 <div class="right"> 88 <ons-button style="background-color: green">${data.message}</ons-button> 89 </div> 90 </ons-list-item>`); 91 }else{ 92 $('#chats').append(` 93 <ons-list-item modifier="nodivider"> 94 <ons-button>${data.message}</ons-button> 95 <span class="list-item__subtitle">${data.userName}</span> 96 </ons-list-item>`); 97 } 98} 99 100// メッセージ送信処理 101const send = () => { 102 const message = $('#message').val(); 103 const userName = localStorage.getItem('userName'); 104 const channel = $('#channelId').val(); 105 ncmb.Script 106 .data({ 107 userName, 108 message, 109 channel 110 }) 111 .exec("POST", "push.js") 112 .then(function(res){ 113 $('#message').val(''); 114 }) 115 .catch(function(err){ 116 console.log(err.name + ':' + err.message); 117 }); 118}; 119

push.js(NCMBスクリプト)
ロジック名   push.js
メソッド    POST
ファイルの状態 実行可能
バージョン   latest

javascript

1const crypto = require("crypto"); 2const request = require('superagent'); 3const NCMB = require('ncmb'); 4module.exports = (req, res) => { 5 const applicationKey = 'MY_NCMB_APPLICATION_KEY'; 6 const clientKey = 'MY_NCMB_CLIENT_KEY'; 7 saveDataStore( 8 applicationKey, 9 clientKey, 10 req.body 11 ).then(() => { 12 return sendPusher( 13 'MY_PUSHER_KEY', 14 'MY_PUSHER_SECRET', 15 'MY_PUSHER_APP_ID', 16 req.body 17 ) 18 }) 19 .then((response) => { 20 res.json({}); 21 }) 22 .catch((err) => res.status(401).json(err)); 23}; 24 25const saveDataStore = (applicationKey, clientKey, body) => { 26 const ncmb = new NCMB(applicationKey, clientKey); 27 const Chat = ncmb.DataStore('Chat'); 28 const chat = new Chat; 29 return chat 30 .set('channel', body.channel) 31 .set('userName', body.userName) 32 .set('message', body.message) 33 .save() 34} 35 36const sendPusher = (authKey, secretKey, appId, body) => { 37 const authTimestamp = Date.now() / 1000; 38 const authVersion = '1.0'; 39 const medhod = 'POST'; 40 const path = `/apps/${appId}/events`; 41 const message = { 42 data: JSON.stringify({ 43 userName: body.userName, 44 message: body.message 45 }), 46 name: "message", 47 channel: body.channel 48 }; 49 const bodyMd5 = crypto 50 .createHash('md5') 51 .update(JSON.stringify(message)) 52 .digest('hex'); 53 const queryString = `auth_key=${authKey}&auth_timestamp=${authTimestamp}&auth_version=${authVersion}&body_md5=${bodyMd5}`; 54 const authSigning = [ 55 medhod, 56 path, 57 queryString 58 ].join("\n"); 59 const signature = crypto 60 .createHmac("SHA256", secretKey) 61 .update(authSigning) 62 .digest("hex"); 63 return request 64 .post(`https://api.pusherapp.com${path}?${queryString}&auth_signature=${signature}`) 65 .set('Content-Type', 'application/json') 66 .send(JSON.stringify(message)) 67}

なお、push.jsの取得結果ログは下記になります。

json

1{ 2 "Status": "DONE", 3 "RequestHeaders": "{\"host\":\"script.mbaas.api.nifcloud.com\",\"connection\":\"close\",\"content-length\":\"68\",\"x-ncmb-timestamp\":\"2020-03-16T07:13:06.154Z\",\"x-ncmb-signature\":\"GmpGgZ5oupwMzVwp9E8gjM7AcDcibIEJeM9vt6dJR+8=\",\"user-agent\":\"Mozilla/5.0 (Linux; Android 7.0; HUAWEI VNS-L22 Build/HUAWEIVNS-L22; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.132 Mobile Safari/537.36\",\"content-type\":\"application/json\",\"accept\":\"text/plain\",\"x-ncmb-sdk-version\":\"javascript-3.0.2\",\"sec-fetch-dest\":\"empty\",\"x-ncmb-application-key\":\"a49971d96d28c90a9310b798083946a4a87a2b50acff4630558fcba804d0e617\",\"origin\":\"file://\",\"x-requested-with\":\"mobi.monaca.debugger\",\"sec-fetch-site\":\"cross-site\",\"sec-fetch-mode\":\"cors\",\"accept-encoding\":\"gzip, deflate\",\"accept-language\":\"ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7\"}", 4 "RequestQuery": "{}", 5 "ResponseHeaders": "{\"Content-Type\":\"application/json\"}", 6 "Error": null, 7 "Duration": 1652, 8 "created_at": "2020-03-16T07:13:05.000Z", 9 "updated_at": "2020-03-16T07:13:07.000Z", 10 "ResponseStatus": 401, 11 "ScriptIdentifier": "push.js" 12}

NCMBのデータストアを確認すると、メッセージは入っているので、そこまでは問題無いと思うので、後はPusherからWebSocket通知がアプリに反映されてないだけだと思うのですが、どこか間違えている部分があればご指摘いただけますでしょうか。
ご教授いただけると助かります。
よろしくお願いします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

まったく同じ事象ではまっていましたが、NCMBスクリプトの最後のほうにあるpostのURLを以下に変更することで、ResponseStatusが200で返ってくるようになり、pusherからメッセージが届くようになりました。

https://api.pusherapp.com

https://api-ap3.pusher.com

※ URLはPusher管理コンソールの「Getting Started」⇒「2 Add this to your server」⇒「Curl」の2行目から取ってきました。

ご参考になれば幸いです。

投稿2020/03/18 06:33

ngtosm

総合スコア18

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

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

T_Furuta

2020/03/18 10:30

ngtosm様 情報、ありがとうございます。 今日は外出しているので確認出来ませんが、明日確認させていただきます。
T_Furuta

2020/03/19 00:19

情報ありがとうございました。 試してみたのですが、今までメッセージを送信した際、メッセージの内容が消えなかったのですが、消えるようになりました。 もう少しだと思うので、調査してみます。 ありがとうございます。
guest

0

pusherが正しく初期化できているかどうか確認してください。この部分です。

js

1pusher = new Pusher(app_id, { 2 cluster: app_cluster, 3 forceTLS: true 4 });

次に、pusherの受信処理が正しくできているかどうかを確認してください。この部分です。

js

1// Pusherに接続する処理 2const connectPusher = (userName, chatId) => { 3 const channel = pusher.subscribe(chatId); 4 channel.bind('message', function(data) { 5 showChat(userName, data); 6 }); 7};

pusherの管理画面からメッセージを飛ばしてみてメッセージが受け取れるかどうか確認してみるのもいいかと思います。後もう一息だと思うので、頑張ってください!

投稿2020/03/16 08:15

moongift

総合スコア250

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

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

T_Furuta

2020/03/16 08:22

moongift様 情報ありがとうございます。ご指摘された点をもう一度確認してみます。
T_Furuta

2020/03/19 00:38

moongift様 情報、ありがとうございました。 確認してみたところ、Pusherの初期化の引数が正しくありませんでした。 app_idを入れるのでは無く、下記のようにkeyを入れるのが正解でした。 ```JavaScript pusher = new Pusher(pusher_key, { cluster: pusher_cluster }); ```
guest

0

moongift様
ngtosm様

情報ありがとうございました。
お二人のおかげで、無事動作させる事が出来ました。
参考までに、動作したソースコードを下記に記載しておきます。

index.html

HTML

1<!DOCTYPE HTML> 2<html> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"> 6 <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'"> 7 <script src="components/loader.js"></script> 8 <script src="lib/onsenui/js/onsenui.min.js"></script> 9 10 <link rel="stylesheet" href="components/loader.css"> 11 <link rel="stylesheet" href="lib/onsenui/css/onsenui.css"> 12 <link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css"> 13 <link rel="stylesheet" href="css/style.css"> 14 <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> 15 <script src="https://js.pusher.com/5.1/pusher.min.js"></script> 16 <script src="js/app.js"></script> 17</head> 18<body> 19 <ons-navigator swipeable id="nav" page="login.html"></ons-navigator> 20 <template id="login.html"> 21 <ons-page id="login"> 22 <div class="join-area" style="text-align: center; margin-top: 30px;"> 23 <h4>チャットルームにログインしてください</h4> 24 <p> 25 <ons-input id="userName" modifier="underbar" placeholder="ユーザ名" float></ons-input><br /> 26 <ons-input id="chatId" modifier="underbar" placeholder="chatId" float></ons-input> 27 </p> 28 <p style="margin-top: 30px;"> 29 <ons-button onclick="join()">Join</ons-button> 30 </p> 31 </div> 32 </ons-page> 33 </template> 34</body> 35</html> 36

chat.html

HTML

1<ons-page id="chat"> 2 <ons-toolbar> 3 <div class="left"><ons-back-button>Back</ons-back-button></div> 4 <div class="center"></div> 5 </ons-toolbar> 6 <input type="hidden" id="channelId" /> 7 <div class="chat-area"> 8 <ons-list id="chats"></ons-list> 9 </div> 10 <div class="send-area"> 11 <ons-input id="message" placeholder="メッセージ"></ons-input> 12 <ons-button onclick="send()" modifier="quiet">送信</ons-button> 13 </div> 14 </ons-page>

JavaScript

1// This is a JavaScript file 2let pusher; 3let ncmb; 4 5const pusher_key = 'MY_PUSHER_KEY'; //ここを、app_idから、Keyに変更しました。 6const pusher_cluster = 'MY_PUSHER_CLUSTER'; 7const applicationKey = 'MY_NCMB_APPLICATION_KEY'; 8const clientKey = 'MY_NCMB_CLIENT_KEY'; 9 10// グローバル変数の処理 11ons.ready(function() { 12 pusher = new Pusher(pusher_key, { 13 cluster: pusher_cluster 14 }); 15 ncmb = new NCMB(applicationKey, clientKey); 16}); 17 18// 初期表示処理 19$(document).on('init', (event) => { 20 if (event.target.id === 'login') { 21 $('#chatId').val('channel'); 22 const userName = localStorage.getItem('userName'); 23 if (userName) 24 $('#userName').val(userName); 25 } 26}); 27 28// チャット画面を表示したときの処理 29$(document).on('show', (event) => { 30 if (event.target.id === 'chat') { 31 const data = event.target.data; 32 $('#channelId').val(data.chatId); 33 connectPusher(data.userName, data.chatId); 34 loadChat(data.userName, data.chatId); 35 } 36}); 37 38// チャット画面から戻った時の処理 39$(document).on('hide', (event) => { 40 if (event.target.id === 'chat') { 41 pusher.unsubscribe($('#channelId').val()); 42 } 43}); 44 45// チャットルームにログインする処理 46const join = () => { 47 const userName = $('#userName').val(); 48 if (userName === '') { 49 ons.notification 50 .alert('ユーザ名を決めてください'); 51 return; 52 } 53 localStorage.setItem('userName', userName); 54 const chatId = $('#chatId').val(); 55 $('#nav')[0].pushPage('chat.html', { 56 data: { userName, chatId } 57 }) 58} 59 60// Pusherに接続する処理 61const connectPusher = (userName, chatId) => { 62 console.log(userName); 63 console.log(chatId); 64 65 const channel = pusher.subscribe(chatId); 66 channel.bind('message', function(data) { 67 showChat(userName, data); 68 }); 69}; 70 71// 既存のチャットメッセージを読み込む処理 72const loadChat = (userName, channel) => { 73 const Chat = ncmb.DataStore('Chat'); 74 Chat 75 .equalTo('channel', channel) 76 .fetchAll() 77 .then(chats => { 78 for (let chat of chats) { 79 showChat(userName, chat); 80 } 81 }); 82} 83 84// メッセージを一つ表示する処理 85const showChat = (userName, data) => { 86 if (data.userName == userName) { 87 $('#chats').append(` 88 <ons-list-item modifier="nodivider"> 89 <div class="right"> 90 <ons-button style="background-color: green">${data.message}</ons-button> 91 </div> 92 </ons-list-item>`); 93 }else{ 94 $('#chats').append(` 95 <ons-list-item modifier="nodivider"> 96 <ons-button>${data.message}</ons-button> 97 <span class="list-item__subtitle">${data.userName}</span> 98 </ons-list-item>`); 99 } 100} 101 102// メッセージ送信処理 103const send = () => { 104 const message = $('#message').val(); 105 const userName = localStorage.getItem('userName'); 106 const channel = $('#channelId').val(); 107 108 ncmb.Script 109 .data({ 110 userName, 111 message, 112 channel 113 }) 114 .exec("POST", "push.js") 115 .then(function(res){ 116 $('#message').val(''); 117 }) 118 .catch(function(err){ 119 console.log(err.name + ':' + err.message); 120 }); 121}; 122

push.js(NCMBスクリプト)
ロジック名   push.js
メソッド    POST
ファイルの状態 実行可能
バージョン   latest

JavaScript

1const crypto = require("crypto"); 2const request = require('superagent'); 3const NCMB = require('ncmb'); 4module.exports = (req, res) => { 5 const applicationKey = 'MY_NCMB_APPLICATION_KEY'; 6 const clientKey = 'MY_NCMB_CLIENT_KEY'; 7 const pusher_key = 'MY_PUSHER_KEY'; 8 const pusher_secret = 'MY_PUSHER_SECRET'; 9 const pusher_appid = 'MY_PUSHER_APP_ID'; 10 saveDataStore( 11 applicationKey, 12 clientKey, 13 req.body 14 ).then(() => { 15 return sendPusher( 16 pusher_key , 17 pusher_secret , 18 pusher_appid , 19 req.body 20 ) 21 }) 22 .then((response) => { 23 res.json({}); 24 }) 25 .catch((err) => res.status(401).json(err)); 26}; 27 28const saveDataStore = (applicationKey, clientKey, body) => { 29 const ncmb = new NCMB(applicationKey, clientKey); 30 const Chat = ncmb.DataStore('Chat'); 31 const chat = new Chat; 32 return chat 33 .set('channel', body.channel) 34 .set('userName', body.userName) 35 .set('message', body.message) 36 .save() 37} 38 39const sendPusher = (authKey, secretKey, appId, body) => { 40 const authTimestamp = Date.now() / 1000; 41 const authVersion = '1.0'; 42 const medhod = 'POST'; 43 const path = `/apps/${appId}/events`; 44 const message = { 45 data: JSON.stringify({ 46 userName: body.userName, 47 message: body.message 48 }), 49 name: "message", 50 channel: body.channel 51 }; 52 const bodyMd5 = crypto 53 .createHash('md5') 54 .update(JSON.stringify(message)) 55 .digest('hex'); 56 const queryString = `auth_key=${authKey}&auth_timestamp=${authTimestamp}&auth_version=${authVersion}&body_md5=${bodyMd5}`; 57 const authSigning = [ 58 medhod, 59 path, 60 queryString 61 ].join("\n"); 62 const signature = crypto 63 .createHmac("SHA256", secretKey) 64 .update(authSigning) 65 .digest("hex"); 66 return request 67     //ここを、https://api.pusherapp.comから、https://api-ap3.pusher.comに変更しました。 68 .post(`https://api-ap3.pusher.com${path}? 69 ${queryString}&auth_signature=${signature}`) 70 .set('Content-Type', 'application/json') 71 .send(JSON.stringify(message)) 72}

投稿2020/03/19 00:50

編集2020/04/24 00:58
T_Furuta

総合スコア25

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

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

todayyy

2020/04/23 21:24

僕もちょうどこの情報について興味があったので大変参考になりました。ありがとうございます。 T_Furutaさん最後のソースコードのpush.jsにPusherのキー諸々が表示されているので、隠したほうがよろしいかいと思います。
T_Furuta

2020/04/24 00:59

todayyy様 多少参考になったようで良かったです。 また、ソースコードのご指摘ありがとうございました。 見逃していたため、助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問