Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8832

【Node.js】Expoプッシュ通知を一斉送信するWebAPI|配列を任意の数に分割をする

$
0
0

はじめに

現在Expo ReactNativeを使ってネイティブアプリ開発をしています。
Expoを使ってプッシュ通知を送るためにプッシュ通知のTokenを1つ、1つPOSTリクエストを飛ばしてもいいのですが、Expoの仕様では最大100個のTokenをまとめてPOSTできる。そこでN個ずつに配列を分割して二次元配列にして処理する方法を紹介します。

以下のような長さ75の配列があるとする、それを10分割して余った分は10個未満になっても分割をする。
今回は長さ75の配列を10個づつ分割して二次元配列にする。

処理前

スクリーンショット 2020-08-12 午後6.59.47.png

処理後

スクリーンショット 2020-08-12 午後7.02.02.png

コード

constmain=()=>{//TOKENにみたて複数の数字を配列にセットletarr=[]for(leti=0;i<75;i++){arr.push(i)}console.log(arr)letresult_arr=[]//分割数constdivision_count=10//配列の数を分割数で割った値を切り上げた値constadd_arr_count=Math.ceil(arr.length/division_count)//add_arr_countの分だけ空配列を追加するfor(leti=0;i<add_arr_count;i++){result_arr.push([])}//いい感じに分割して配列にいれるarr.forEach((item,index)=>{result_arr[Math.floor(index/division_count)].push(item)})console.log(result_arr)}(async()=>{main()})()

Expoを使って実際に通知を送る

私の環境ではNode.jsを使ってWebAPIを作り、まとめて送信できるようにしています。
また、Token一覧を管理しているのはMySQLを使っています。

Request body
プッシュ通知のタイトルを設定するpush_titleとプッシュ通知の本文部分にあたるpush_body載せてください

※本物のコードは外部から実行できないようにセキュリティ対策をしています

コード

constexpress=require('express')// expressモジュールを読み込むconstcors=require('cors')//クロスドメインでアクセスを許可する系のやつconstbodyParser=require('body-parser')//いい感じにGET POSTを解釈するやつconstutil=require('util')// SQL Async/Awaitconstaxios=require('axios')//npm install axiosconstmysql=require('mysql')constmulter=require('multer')// multerモジュールを読み込む これがないとBODYの中身をうまく読み取らない//↑ 各種、「npm install」してください//↑ 各種、「npm install」してください//↑ 各種、「npm install」してください// 例1 npm i express// 例2 npm i corsconstapp=express()// expressアプリを生成するapp.use(bodyParser())app.use(express.static('web'))// webフォルダの中身を公開するapp.use(cors())//CROS許可app.use(multer().none())// multerでブラウザから送信されたデータを解釈する//サーバの受付ポート番号、SQL接続情報、設定ファイル読み込みconstconfig=require('./server_config.json')// config.server.portのポートでサーバを立てるapp.listen(config.server.port,()=>console.log('Listening on port '+config.server.port))//MySQL接続情報Async/Await★★★★★★★★★★★★★★★★★★★★★★★★★★★★//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★constpool_config={host:config.sql.host,user:config.sql.user,password:config.sql.password,port:config.sql.port,database:config.sql.database,timezone:config.sql.timezone//timezoneの指定省略の場合はシステムローカルになる}//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★//汎用的にMySQLを発行するconstrunQuery=async(sql,data)=>{console.log('runQuery...')console.log('sql: '+sql)console.log('data: '+data)constpool=mysql.createPool(pool_config)pool.query=util.promisify(pool.query)//これないと動かないconstrun_sql=mysql.format(sql,data)console.log('発行されたquery:\n'+run_sql+'\n')constresult=awaitpool.query(run_sql)// console.log(JSON.stringify(result))pool.end()// mysqlのコネクションのプロセスを終了させる。returnresult}constuuid=require('node-uuid')app.post('/api/v1/expoPushNotice',(req,res,next)=>{(async()=>{console.log('/api/v1/expoPushNotice...')//私の環境ではMySQLでpush_tokenというTableを作ってそこでTokenを保存していますletpush_token_list=awaitrunQuery('select `push_token` from `push_token`',[])//通知を送るtokenletto_tokens=[]//分割数constdivision_count=100//配列の追加数 切り上げた値の数だけ配列を追加constadd_arr_count=Math.ceil(push_token_list.length/division_count)console.log('add_arr_countの文だけから配列を追加する')//add_arr_countの文だけから配列を追加するfor(leti=0;i<add_arr_count;i++){to_tokens.push([])}push_token_list.forEach((item,index)=>{to_tokens[Math.floor(index/division_count)].push(item.push_token)})console.log('to_tokens: ')console.log(to_tokens)//APIコールconsole.log('pushSend...')constreq_url='https://exp.host/--/api/v2/push/send'constheaders={headers:{Accept:'application/json','Accept-encoding':'gzip, deflate','Content-Type':'application/json',},}//分割した分で別々にPOSTリクエストを飛ばすfor(leti=0;i<to_tokens.length;i++){//bodyに好きなデータを載せると、アプリ側でいろいろできます。constresult=awaitaxios.post(req_url,{'to':to_tokens[i],'sound':'default','title':req.body.push_title,'body':req.body.push_body,'data':{},},headers)console.log('result: ')console.log(result)}res.json({status:200,//message:'リクエストは正常に受信されました',})})(res,next).catch((e)=>{console.log('サーバエラー : '+e)console.log('res : '+res)console.log('e : '+e)res.json({status:500,message:'サーバエラー\n'+next,})})})

Tokenを保存しているDB情報

CREATETABLE`push_token`(`id`int(11)unsignedNOTNULLAUTO_INCREMENT,`push_token`varchar(255)DEFAULTNULL,PRIMARYKEY(`id`),UNIQUEKEY`push_token`(`push_token`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8;

サーバの設定ファイルを記述しているJSONファイル

{"sql":{"host":"localhost","user":"hoge","password":"hoge","port":8889,"database":"fuga","timezone":"jst"},"server":{"port":3003}}

Viewing all articles
Browse latest Browse all 8832

Trending Articles