- 投稿日:2020-10-21T22:50:18+09:00
Nodeのプロミスって??
はじめに
Nodeのプロミスについて、自分なりにまとめてみることにしました。
プロミスとは
プロミスを簡単に説明するなら、「非同期処理の結果の値(失敗も含む)を表現するオブジェクト」です。
プロミスの動作
- 非同期処理をする、ある関数(Function A)があった時、このFunction Aを呼び出すとPromiseを返します。
- このPromiseは、非同期処理が完了(fulfilled) or 非同期処理が失敗(rejected)のどっちかが起きることは保証されています。
- このPromiseがfulfilled/rejectedが起きていない場合は、非同期処理が完了していない(pending)の状態となります。
プロミスの状態まとめ
つまり、プロミスは3つの状態があります。
- 非同期処理が完了(fulfilled)
- 非同期処理が失敗(rejected)
- 非同期処理が完了していない(pending)
プロミス使用パターン
Promise.then([ハンドラ関数A],[ハンドラ関数B])
・ パターンとして、成功の場合に呼び出す関数をハンドラ関数A、失敗したときに呼び出す関数をハンドラ関数Bを呼ぶようにすると、非同期処理が完了し、プロミスが成功した時はハンドラ関数Aが実行され、失敗したときはハンドラ関数Bが実行されます。
.then() は処理結果を受け取り、新しいプロミスオブジェクトを作成して戻り値として返却するメソッドです。
・ 図は、はじめのPromise Xが解決された後、ハンドラ関数の戻り値によりPromise Yが解決される流れをイメージしています。[結構この図、力作ですw]
参考文献
- 投稿日:2020-10-21T22:50:18+09:00
非同期パターン(プロミスって??)
はじめに
非同期パターンのプロミスについて、自分なりにまとめてみることにしました。
プロミスとは
プロミスを簡単に説明するなら、「非同期処理の結果の値(失敗も含む)を表現するオブジェクト」です。
プロミスの動作
- 非同期処理をする、ある関数(Function A)があった時、このFunction Aを呼び出すとPromiseを返します。
- このPromiseは、非同期処理が完了(fulfilled) or 非同期処理が失敗(rejected)のどっちかが起きることは保証されています。
- このPromiseがfulfilled/rejectedが起きていない場合は、非同期処理が完了していない(pending)の状態となります。
プロミスの状態まとめ
つまり、プロミスは3つの状態があります。
- 非同期処理が完了(fulfilled)
- 非同期処理が失敗(rejected)
- 非同期処理が完了していない(pending)
プロミス使用パターン
Promise.then([ハンドラ関数A],[ハンドラ関数B])
・ パターンとして、成功の場合に呼び出す関数をハンドラ関数A、失敗したときに呼び出す関数をハンドラ関数Bを呼ぶようにすると、非同期処理が完了し、プロミスが成功した時はハンドラ関数Aが実行され、失敗したときはハンドラ関数Bが実行されます。
.then() は処理結果を受け取り、新しいプロミスオブジェクトを作成して戻り値として返却するメソッドです。
・ 図は、はじめのPromise Xが解決された後、ハンドラ関数の戻り値によりPromise Yが解決される流れをイメージしています。[結構この図、力作ですw]
参考文献
- 投稿日:2020-10-21T22:50:18+09:00
非同期のパターン(プロミスって??)
はじめに
非同期パターンのプロミスについて、自分なりにまとめてみることにしました。
プロミスとは
プロミスを簡単に説明するなら、「非同期処理の結果の値(失敗も含む)を表現するオブジェクト」です。
プロミスの動作
- 非同期処理をする、ある関数(Function A)があった時、このFunction Aを呼び出すとPromiseを返します。
- このPromiseは、非同期処理が完了(fulfilled) or 非同期処理が失敗(rejected)のどっちかが起きることは保証されています。
- このPromiseがfulfilled/rejectedが起きていない場合は、非同期処理が完了していない(pending)の状態となります。
プロミスの状態まとめ
つまり、プロミスは3つの状態があります。
- 非同期処理が完了(fulfilled)
- 非同期処理が失敗(rejected)
- 非同期処理が完了していない(pending)
プロミス使用パターン
Promise.then([ハンドラ関数A],[ハンドラ関数B])
・ パターンとして、成功の場合に呼び出す関数をハンドラ関数A、失敗したときに呼び出す関数をハンドラ関数Bを呼ぶようにすると、非同期処理が完了し、プロミスが成功した時はハンドラ関数Aが実行され、失敗したときはハンドラ関数Bが実行されます。
.then() は処理結果を受け取り、新しいプロミスオブジェクトを作成して戻り値として返却するメソッドです。
・ 図は、はじめのPromise Xが解決された後、ハンドラ関数の戻り値によりPromise Yが解決される流れをイメージしています。[結構この図、力作ですw]
参考文献
- 投稿日:2020-10-21T20:34:50+09:00
【React + TypeScript】プロジェクト開始時tsconfig.jsonに追記しておくべき設定2点
はじめに
TypeScriptでReactアプリを作成する際、TypeScript設定ファイルの「tsconfig.json」に追記しておくと良い設定について記録しておきます。
アプリはnodeインストール済みの環境で以下コマンドを発行して作成したものとします。
npx create-react-app hello-world --template typescript追記後のtsconfig.json
「"baseUrl": "src"」と「"downlevelIteration": true」を追記しています。
hello-world/tsconfig.json{ "compilerOptions": { "target": "es5", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react", "baseUrl": "src", "downlevelIteration": true, }, "include": [ "src" ] }"baseUrl": "src"
追記しておくと、
node-modules/
にインストールされていないモジュールをインポートする時(src配下に自分で作成したモジュールなど)、src/
を起点としたパスで指定することができます。例として
src/components/pages/home.tsx
からsrc/components/atoms/button.tsx
を参照する際、この設定が無い場合相対パスをつなげて書かなければならないですがsrc/components/pages/home.tsximport * from '../../atoms/button'この設定を追記することで
src/components/pages/home.tsximport * from 'components/atoms/button'このように書くことができます。
"downlevelIteration": true
コンパイルターゲットをES5以前に設定している場合(「"target": "es5"」)でも、ES2015から導入された便利な記述をES5以下で実行できるようよしなに書き下してくれます。
この設定が無ければ新機能を使用した記述によるコンパイルエラーが発生してしまう可能性も有るので、最初から有効にしておくと良いです。
以上です。お疲れ様でした
- 投稿日:2020-10-21T18:56:50+09:00
nginx + expressをfargate 4coreで動かす
- nginx + expressをfargateに詰め込む
- unix socket を使って繋ぐ
- expressは4プロセス立ち上げる
- node clusterは使わないパターン、socketが競合してしまったので。
- 共通ボリュームにapi1.sock - api4.sockを設定して、nginxからupstreamする
api
共通ボリュームをVolumeにしておく
VOLUME /usr/src/tmpsockのパスを環境変数で指定させる
main.jsconst sock = process.env.SOCK_PATH; app.listen(sock, () => { fs.chmodSync(sock, '666'); console.log(`Server running on ${sock} with pid ` + process.pid); });nginx
api1.sock - api4.sockへupstreamする
nginx.confupstream api { server unix:///usr/src/tmp/api_1.sock; server unix:///usr/src/tmp/api_2.sock; server unix:///usr/src/tmp/api_3.sock; server unix:///usr/src/tmp/api_4.sock; } server { listen 80 default; listen [::]:80; location / { proxy_pass http://api; break; } }タスク定義
ECSタスク定義で、繋ぐ
task-define.json{ "containerDefinitions": [ { "name": "nginx", "portMappings": [ { "hostPort": 80, "protocol": "tcp", "containerPort": 80 } ], "mountPoints": [ { "readOnly": true, "containerPath": "/usr/src/tmp", "sourceVolume": "etc" } ] }, { "name": "api1", "mountPoints": [ { "containerPath": "/usr/src/tmp", "sourceVolume": "etc" } ], "environment": [ { "name": "SOCK_PATH", "value": "/usr/src/tmp/api_1.sock" } ] }, { "name": "api2", "mountPoints": [ { "containerPath": "/usr/src/tmp", "sourceVolume": "etc" } ], "environment": [ { "name": "SOCK_PATH", "value": "/usr/src/tmp/api_2.sock" } ] }, { "name": "api3", "mountPoints": [ { "containerPath": "/usr/src/tmp", "sourceVolume": "etc" } ], "environment": [ { "name": "SOCK_PATH", "value": "/usr/src/tmp/api_3.sock" } ] }, { "name": "api4", "mountPoints": [ { "containerPath": "/usr/src/tmp", "sourceVolume": "etc" } ], "environment": [ { "name": "SOCK_PATH", "value": "/usr/src/tmp/api_4.sock" } ] } ], "volumes": [{ "name": "etc" }], }
- 投稿日:2020-10-21T17:48:43+09:00
React開発時の汎用的なGitpod環境設定
- 開発時に、オンラインエディタであるGitpodを利用する機会があります。
- 同様の技術利用が多いため、環境テンプレートを作成する必要があります。
- 今回はReactを利用した開発においてのGitpod設定を記述します。
- ※Gitpodの概要や利用方法に関しては、こちら
前提
- Reactプロジェクトの準備
- 試用の場合、create-react-app等で準備
- ※npmプロジェクトであれば基本可
結果
- 先にGitpod設定ファイルである、
.gifpod.yml
の記述を示します。tasks: - init: npm ci command: npm start ports: - port: 3000 onOpen: open-preview github: prebuilds: addComment: true addBadge: true vscode: extensions: - dbaeumer.vscode-eslint@2.1.8:02aHhbJ0Q4aGdjHXlTdVKg== - esbenp.prettier-vscode@5.7.1:GDba64T6G+TUi1qmc6BE3A== - dsznajder.es7-react-js-snippets@3.0.0:9YEGn/57fW8lJt7cVxJQDQ==
- 以下、実際のGitpodでの開発画面。
内容
- 上記の結果は、主に以下を設定した開発環境を用意するための記述です。
- 環境構築時の自動コマンド指定
- 自動プレビュー
- 起動速度の短縮
- vscode拡張機能の自動追加
起動コマンド指定
.gitpod.yml
では、tasks
で環境構築時の自動コマンド指定が可能です。- そのため、React開発時に必要な以下を設定します。
- 依存関係インストール
init
(新規作成時のみ実行)プロパティで設定
- ※再起動やスナップショット時は行われない
- 開発サーバー起動
command
(開始時に毎回実行)プロパティで設定自動プレビュー
.gitpod.yml
では、ports
サーバー動作設定が可能です。- タブ抑止のため、
open-preview
でエディタ画面内にプレビューの表示を行います。起動速度の短縮
- オンラインエディタでは、起動速度が遅い場合があります。
- Gitpodでは、Githubアプリ連携によるプレビルド機能により大幅な解消が可能です。
- ※基本デフォルトで十分のため、githubで連携するのみで記述は必須では無い。
- ※拡張の場合のみ、prebuildsプロパティを記述
vscode拡張機能の自動追加
まとめ
- 上記のことから、オンライン開発環境における最低限の定型化と良質な開発性の重要性を実感。
参考
- 投稿日:2020-10-21T17:43:12+09:00
[作り方] discord.js グローバルVC(グローバルボイスチャット)
グローバルVCを作ってみた。
NeoXBotというdiscordのbotを作ったときに、
グローバルボイスチャットのリクエストがあったので、
先月ごろ作りました。準備
・"discord.js"
をnpmからインストールnpm install discord.js・音声用に
"discordjs/opus"
を同じくnpmからインストールnpm install @discordjs/opus/** DiscordID:696600519283572766 ©X / KOU00000 orichalcum.gom@gmail.com */ //グローバルボイスチャットの名前 const gvcName = "グローバルボイスチャット"; const token = "あなたのbotのtoken" const discord = require("discord.js"); const client = new discord.Client(); client.login(token); //音データ作成用 const {Readable}=require('stream'); //音の流れない音データを作る。 class Silence extends Readable{ _read(){this.push(Buffer.from([0xF8,0xFF,0xFE]))} }; /** * discord の client が ready 状態になってないと、 * client.channels..... を行えない。 */ client.on("ready",()=>{ console.info("ready...") client.channels.cache.filter //グローバルボイスチャットが変数gvcNameと同じチャンネルを抽出 (ch=>ch.type === "voice" && ch.name === gvcName) .forEach(ch=> { ch.join()//vcに参加 .then(conn => {//connに参加したvcのデータが含まれる。 //音の流れない音データを配信 //(最初にbotがVCで音データを流さないと音の取得ができないため。) conn.play(new Silence,{ type: 'opus' }); let receiver = conn.receiver; //だれかがVCで発言したら。 conn.on('speaking', (user, speaking) => { //botだったら放送しない。 if(user.bot)return; //音を取得 const UserVoice = receiver.createStream(user); const broadcast = client.voice.createBroadcast(); //流す音 broadcast.play(UserVoice,{ type: 'opus' }); //一斉にbotが接続中のVCに取得した音声を配信。 for (const connection of client.voice.connections.values()) { connection.play(broadcast); }; }); }); }); });※ ※ ※
ここにのせたコードは、
NeoXBotに搭載してるものとは別に、
公開用にシンプルにしたバージョンのコードなのですが、
ちゃんとしたテストなどを行っていないので、
もしかしたらちゃんと動かないかもしれないです。
答えられる限り答えるので、何かあればコメントでお願いします。
- 投稿日:2020-10-21T12:29:38+09:00
吉報報告アプリをつくってみた!っていう話
コロナ渦の中、皆様いかがお過ごしですか?
少しでも元気になるシステム開発できないかな〜と思いまして、
吉報を全社で喜ぶためのアプリを開発しました。プログラムの詳細は、書かないですが、どんな構成で作ったかを紹介します!
開発リミットが2日しかなかったので、作り込んではいないです。?
(そのうちの1日はどんな音楽がテンション上がるかで費やしました。)吉報を報告するアプリってどんなの?
チャットワークに、メッセージを送るとMacをつないでいるモニターにテンションが上がる音楽とともに吉報が報告されます。
アーキテクチャ
※あつまるBotに対してToをつけた場合だけ全社への報告になるようにしています?
②チャットワークAPIを受け取り、データを加工
③FirebaseのRealtime Databaseを更新
④Electronで作成したMacアプリ側で、データを受け取る
⑤Cloud StorageからBGMをダウンロードして音楽を流し、メッセージを画面に流す
※報告内容によって、ダウンロードする音楽を切り分けています。どこにつまづいたか
ブラウザに依存させず、Mac本体に制御を加えたかったので、Macアプリ作ろうと思い立ちました。
いろいろ方法はあるものの、久々に"Electron"を触ってみました。《つまづきポイント①》
Electron側のウィンドウの制御
イメージは下の図のようになっています。
透明な全画面ブラウザを上にマスクさせて、CSSでメッセージが流れる表現をしています。
Electronの画面の表現には慣れていなかったので、いろいろ苦戦しました。?
mainWindow.setIgnoreMouseEvents(true);
ウィンドウをクリックできない状態にするmainWindow.setAlwaysOnTop(true, 'floating');
ウィンドウを最前面表示ウィンドウ制御周りのコード
// メインウィンドウを作成します let size = screen.getPrimaryDisplay().size; // ディスプレイのサイズを取得する mainWindow = new BrowserWindow({ webPreferences: { nodeIntegration: true, }, left: 0, top: 0, frame: false, // フレームを非表示にする resizable: false, // ウィンドウリサイズ禁止 transparent: true, width: size.width, height: size.height, skipTaskbar: true, alwaysOnTop: true // 一番手前に表示する }); // 全てのウィンドウに表示(フルスクリーン対応) app.dock.hide(); mainWindow.setAlwaysOnTop(true, 'floating'); mainWindow.setVisibleOnAllWorkspaces(true); mainWindow.setFullScreenable(false); app.dock.show(); // マウスイベント無効化 mainWindow.setIgnoreMouseEvents(true);
app.dock.hide();
して、app.dock.show();
する一連の流れについては、謎挙動。。。
しかし、この流れでなければ、最前面&フルスクリーンは実装できませんでした。《つまづきポイント②》
つまづきポイントを書こうと思ったのですが、つまづきポイント①で書いたところ以外は、
特につまづきませんでした。。。とにかくFirebaseが便利すぎて、助けられました。作ってみてどうだったか
このアプリを会社に導入してから、1日に8回くらい吉報が流れます。?
多い時は、15回以上流れることもありました?《社内と気持ちの変化》
- 喜びを部署超えて、全社に共有できる(他の部署のことを知ったり、話すきっかけにもなる)
- テンションがあがり、早く吉報を報告したい気分になる
何より、使ってもらえることが作った側からすると一番嬉しいです☺️
今後の展望
吉報を報告した人、内容によって、BGMを分けたり、画面のギミックを変えたりできるともっともっとテンションが上がって、吉報を報告したい気持ちが高まりそう。
あとは、社内だけでなく、他の会社でもこのアプリを使ってもらえると嬉しいなと思います。
ぜひ、興味ある方、声かけてください〜?