20210607のNode.jsに関する記事は8件です。

Nuxt.jsでGoogleBooksAPIを使用して検索結果を表示してみた

1.はじめに 2.内容 3.おわりに 1. はじめに GoogleBooksAPIとaxiosを使用して書籍検索システムを作りました。 画像とタイトルを表示させたいと思います。 2. 内容 axiosでGoogleBooksAPIからデータを取得 GoogleBooksAPIから情報を取得するたにaxiosでリクエストを送ります。 data () { return { books: [], keyword: '', url: 'https://www.googleapis.com/books/v1/volumes?q=' } } URLとユーザーが検索できるkeywordはdataで取り扱います。空のbook配列には取得した書籍データを格納します。 <v-text-field v-model="keyword" /> keywordはtemplateのテキストと結び助けておくことで検索機能として動くようにしました。 methods: { get () { this.$axios.$get(this.url + this.keyword + '&maxResults=15') .then(this.setBooks) }, setBooks (res) { this.books = res.data.items } keywordを入力した後に検索ボタンを押すとgetメソッドが発火して書籍情報を取得→bookに格納というように動いてくれます。 <v-card v-for="book in books" :key="book.id" class="ma-0" > <v-row> <v-cols class="my-4 ml-7"> <img :src="volumeInfo.imageLinks.thumbnail"> </v-cols> <v-cols> <v-card-title>{{ book.volumeInfo.title }}</v-card-title> <v-card-text>{{ book.volumeInfo.authors) }}</v-card-text> </v-cols> </v-row> </v-card> items以降のデータを取り出してfor文で表示させたら完成です 問題が見つかる 問題が見つかりました。タイトルや著者情報がない時や、サムネイル画像がないとundefinedでエラーになってしまいます。特に画像のない本が結構あったので対策は必須です。 解決策① v-ifを使って条件分岐で情報を切り替える これは真っ先に思いついたのですが、だいぶ冗長になってしまうのと、そもそも公式で非推奨のやり方になってるのでやめました。 解決策② methodsで条件分岐してくれるオブジェクトを作成 スマートだしかっこいい気がする!ということでこちらを採用! title (valu) { return valu.volumeInfo.title ? valu.volumeInfo.title : 'No title' }, authors (valu) { return valu.volumeInfo.authors ? valu.volumeInfo.authors : 'No authors' }, image (valu) { return valu.volumeInfo.imageLinks ? valu.volumeInfo.imageLinks.thumbnail : noImage } <v-cols class="my-4 ml-7"> <img :src="image(book)"> </v-cols> <v-cols> <v-card-title>{{ title(book) }}</v-card-title> <v-card-text>{{ authors(book) }}</v-card-text> </v-cols> 引数をとって処理を分けることでかっこよくなりました。 こういうのってなんか気持ちいですよね〜 5. おわりに これでなんとか検索結果を表示させることはできました。初めての実装でしたが オブジェクトを用意して条件分岐をするというのは非常に勉強になりました。 課題〜誰か助けて〜 今度はオブジェクトとfor文を使って表示させた画像、タイトル、著者をクリックするとすぐ下に表示されるという機能を追加したいです。やり方を考えているのですが、なかなか見つけられないのと、思いつかなくて困っています。誰か教えてください泣 ①検索リスト表示 ←今回のとこ ②ユーザークリック ③クリックした情報がすぐ下に表示される  ← ここがわからない ④表示されたものを保存する という流れを想定しています。 とりあえず根気強く調べてみようと思います。ではまた!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsからPostgreSQLへ トランザクション管理メソッド実装

はじめに トランザクション内で処理を行いたいとき、BEGINして~クエリ書いて~COMMITして~エラーならROLLBACKして~を毎回書くのは大変ですし、抜け漏れが発生する恐れがあるので、メソッドとして共通化してしまうことにしました。 環境としては、Node.jsからpgモジュールを使用して、Linuxサーバ上のPostgreSQLへの接続となります。 ちなみに前回までの記事はこちらになるので、参考にしてみてください。  LinuxサーバーにPostgreSQL導入~外部サーバー接続まで  Node.jsからPostgreSQLへコネクションプールを使った接続 実際のコード pool.js const { Pool } = require("pg"); // 接続先文字列 const connectionString = 'postgres://user:pass@DBのアドレス:ポート/DB名'; // DB情報をもったプールを生成 const pool = new Pool({ connectionString: connectionString, max: 2 // 保持するコネクション数 }); pool.tx = async (cb) => { const connection = await pool.connect(); let res; try { await connection.query('BEGIN'); try{ res = await cb(connection); await connection.query('COMMIT'); } catch(err) { await connection.query('ROLLBACK'); throw err; } } catch(err) { throw err; } finally { connection.release(); } return res; } module.exports = pool; index.js const express = require('express'); const app = express(); const pool = require('./pool.js'); app.get('/', async function(req, res, next) { let result; try { result = await pool.tx(async client => { const res = await client.query('SELECT NOW()'); // ➀ const res = await client.query('SELECT NOW()'); // ➁ const res = await client.query('SELECT NOW()'); // ➂ return res; }); } catch(err) { console.error(err); res.sendStatus(500); return; } res.status(200).json({data: result.rows}) }); app.listen(3001, () => console.log(`listening on port 3001!`)); コールバック関数内に複数のクエリを書くことで、それらが1つのトランザクション内のクエリとなります。 上のソース内で言うと➀➁➂が1つのトランザクション内にまとまるということです。 最後に pg-promiseモジュールだとtxっていうメソッドで、たしか勝手にトランザクション管理してくれるんですよね。 そのうち、pgとpg-promiseの違いについてもまとめてみようと思います。 (ほかにもpg-poolとかあるっぽいので、できればそれも…)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Node.js】ドメイン名からIPアドレスを取得する

3000文字Tips - 知ると便利なTipsをみんなへ届けよう の参加記事です。 タイトル通りです。 同じようなことはこのサイトでも可能です。 しかし、IP制限されているサーバーの場合、こういった外部サイトでは取得できません。 そのため、手元で試す方法を調べました。 環境 $ node -v v13.11.0 $ npm -v dns 6.13.7 結論 ドメイン名→IPアドレス (v4) const dns = require("dns"); const dnsPromises = dns.promises; dnsPromises.lookup("google.com").then(({ address, family }) => { console.log("address: %j family: IPv%s", address, family); // address: "172.217.25.110" family: IPv4 }); ドメイン名→IPアドレス (v6) const dns = require("dns"); const dnsPromises = dns.promises; const options = { family: 6, hints: dns.ADDRCONFIG | dns.V4MAPPED, }; dnsPromises.lookup("google.com", options).then((result) => { console.log("address: %j family: IPv%s", result.address, result.family); // address: "::ffff:216.58.220.142" family: IPv6 }); 参考 DNS | Node.js v16.3.0 Documentation
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

typescriptでArrayを指定数毎に区切る

こういう感じで、配列を指定数毎に区切りたい describe("chunk test", () => { it("number", () => { expect(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)).toStrictEqual([ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10], ]); }); it("string", () => { expect(chunk(["one", "two", "three", "four"], 2)).toStrictEqual([ ["one", "two"], ["three", "four"], ]); }); }); これで出来ました export function chunk<T>(arr: Array<T>, size: number): Array<Array<T>> { return arr.reduce( (newarr: Array<Array<T>>, _: T, i: number) => i % size ? newarr : [...newarr, arr.slice(i, i + size)], [] as Array<Array<T>> ); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】Laravel Mixの周辺について理解する

Laravel Mixとは、 PHPフレームワーク「Laravel」に同梱されているビルドツールです。 現在主流のWebpackがベースになっており、Laravelを使用しなくても使うことができます。 とにかく設定ファイルがシンプルで、ビルド(ソースコードなどを元に実行可能ファイルや配布パッケージを作成する処理や操作のこと/コンパイルを含む)のスピードも申し分ありません。 package.jsonに設定を記入すると、Webpackやsassの環境構築、Bootstrapのセットアップなどを、 時間をかけずに自動的に圧縮等の処理をしてくれます。 Webpack モジュールをバンドル(束ねる)するツールです。 モジュールとは、プログラム内のJavaScriptファイル(以下:jsファイル)やsassファイルなどのことです。webpackを使うことで、複数のjsファイルをひとつのjsファイルにまとめたり、複数のsassファイルをひとつのsassファイルにしたりできます。 https://goworkship.com/magazine/how-to-webpack/ Bootstrap Twitter社が開発したCSSの「フレームワーク」です。通常CSSを書く場合、全てのスタイルを自分で作っていく必要がありますが、このフレームワークにはよく使われるスタイルがあらかじめ定義してあるので、ルールに沿って利用するだけで整ったデザインのページを作成できます。 node.js PHPのようにサバ―サイドでJavaScriptを動かせるプラットフォームがあり、中でも代表的なのがNode.jsだ。他にそこまで有名なものもないので、「Node.js = サーバサイドJavaScript」だと認識しておけばいいだろう。 サーバサイドで動くというとPHPなどと一緒だと思われたかもしれないが、実はまったく違う。 そもそもNode.jsがサーバサイドで動くプログラムという説明自体が正確ではない。より正確に言うと、Node.jsはサーバサイドでJavaScriptを実行できるようにしてくれるものだ。プラットフォームという表現が正しい。 node.js のバージョンを管理するnodebrew nodebrewを使うことで、一つの環境に複数のバージョンのNode.jsを導入することができます。 Web開発でNode.jsが頻繁に使われる昨今、特にnpmのバージョン互換性が問題となる場合が多いです。そんな中で、複数のプロジェクト用に別々のパッケージを保持したNodeを管理できたり、Nodeのバージョンを即座に切り替えたりできるのは大きなメリットだと思います。 ディレクトリ直下にあるwebpack.mix.jsを編集し、 作成したsassファイルをコンパイルするように記入する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

express-generator-typescriptで、npm start:devができないとき

express-generator-typescriptとは? express-generatorをTypeScriptで構築済みでなおかつ認証機能もついているという大変便利なものです。 GitHub npm 問題点 初期状態で、npm startやnpm start:devを実行したら、以下のようなエラーが出ます。 SyntaxError: Unexpected token } in JSON at position 573 at JSON.parse (<anonymous>) at parse (/hoge/node_modules/tsconfig/src/tsconfig.ts:195:15) at readFileSync (/hoge/node_modules/tsconfig/src/tsconfig.ts:181:10) at Object.loadSync (/hoge/node_modules/tsconfig/src/tsconfig.ts:151:18) at readConfig (/hoge/node_modules/ts-node/src/index.ts:425:18) at Object.register (/hoge/node_modules/ts-node/src/index.ts:189:18) at Object.<anonymous> (/hoge/node_modules/ts-node/src/_bin.ts:140:17) at Module._compile (internal/modules/cjs/loader.js:1063:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Module.load (internal/modules/cjs/loader.js:928:32) 対応方法 一見するとライブラリのエラーなので、どうしようももなさそうですが、問題は、tsconfig.jsonの中にあります。 不要な末尾に対するカンマがあったため、エラーが出たようです。 tsconfig.json /** 省略 **/ "paths": { "@daos/*": [ "src/daos/*" ], "@entities/*": [ "src/entities/*" ], "@shared/*": [ "src/shared/*" ], "@server": [ "src/Server" ] },←このカンマを削除する }, "include": [ "src/**/*.ts", "spec/**/*.ts" ], "exclude": [ "src/public/" ] } 最後に もうしかしたら、私の環境だけこうなっている可能性と英語力に自信がないので、Issuesに報告しようか迷っています。 しかし、この記事がきっかけで、express-generator-typescriptの利用を諦めていた人が救われたら幸いです。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

連番画像からループ部分を抜き出す / パターン配列からループ部分を抜き出す

はじめに タイトルの通りですが、連番画像からループ部分を取り出す必要があり、軽く検索したくらいでは望みの参考文献が出てこなかったので、メモします。 TL;DR 記述は TypeScript ですが、考え方はどの言語でも共通で使えると思います。 前提条件 画像やパターンは毎ループ完全一致する事(ゆらぎ許容度0) ループは2回以上繰り返している事 実装 画像パターン検出には sharp を使っています。 ループが検出できなかったら null を返します。 import sharp from "sharp"; export async function detectLoop( files: string[] ): Promise<{ start: number; end: number; } | null> { // 画像パターン検出 const pattern: number[] = []; const buffers: Buffer[] = []; main: for (const file of files) { const b = await sharp(file).raw().toBuffer(); for (let i = 0; i < buffers.length; i++) { if (buffers[i].equals(b)) { pattern.push(i); continue main; } } buffers.push(b); pattern.push(buffers.length - 1); } //ループ検出 for ( let loopStartIndex = 0; loopStartIndex < pattern.length; loopStartIndex++ ) { length: for ( let loopFrameLength = 2; loopFrameLength < pattern.length / 2; loopFrameLength++ ) { for ( let checkIndex = loopStartIndex + loopFrameLength; checkIndex < pattern.length; checkIndex++ ) { const org = ((checkIndex - loopStartIndex) % loopFrameLength) + loopStartIndex; if (pattern[org] !== pattern[checkIndex]) continue length; } return { start: loopStartIndex, end: loopStartIndex + loopFrameLength - 1 }; } } return null; } 解説 画像パターン検出 const pattern: number[] = []; // A const buffers: Buffer[] = []; // B main: for (const file of files) { const b = await sharp(file).raw().toBuffer(); // C for (let i = 0; i < buffers.length; i++) { if (buffers[i].equals(b)) { // D pattern.push(i); continue main; } } // E buffers.push(b); pattern.push(buffers.length - 1); } まずパターン配列を用意します。(A/B) 配列が2種類ありますが、A が後でループ検出に使用するパターン配列、 B が画像の一致判定に使う Buffer の配列です。実際には B だけでも成立するのですが、処理が重くなりそうなので B を使ってパターン判別をした後、パターン番号を A に格納するという方法を採っています。 C で画像の Buffer を取得した後 D で今までに取得した Buffer と比較し、一致するものがあればインデックスをパターン番号として記録して次のループに進みます。 (全く同じ画像だった場合、buffers[i].equals(b) が true を返します。) もし今までにない Buffer だった場合は、 E に進んで Buffer を登録し、最後のインデックスをその画像のパターン番号として記録します。 これで画像のパターンリスト (A) が出来ました。 ループ検出 どうやってループを検出するか? 基本的には力業です。 例えば先程作ったパターン配列の中身が以下のようなものだったとしましょう。 000111222333000111222333000111222333 総当たりでチェックする (1) 000111222333000111222333000111222333 ** --1× (2) 000111222333000111222333000111222333 *** ---× (3) 000111222333000111222333000111222333 **** ----× …省略 (n) 000111222333000111222333000111222333 ************ ------------●●●●●●●●●●●●●●●●●●●●●●●● ちょっと分かりにくいですが… *(アスタリスク)で表されているのがチェックするパターン、その下にあるのが合否判定です。チェックするパターンの長さを1つずつ変えて判定していっています。 (1)は最初の1つだけ合致していますが、その次で失格。(2)(3)は、最初から合致していません。これを繰り返していき、最後まで失格しなかったパターンをループとして判定します。 開始点をずらす では、次は以下のようなパターンだったとしましょう。 00000111222333000111222333000111222333 基本的には同じパターンですが、最初に余計な 00 が入ってしまっています。 このように、例えば「映像を手動でキャプチャした」等で 最初のパターンがループの開始点ではない可能性があります。 この場合、ループが成立せず検出が不可能になってしまいます。 これを回避するため、 ループ開始点をずらしたパターンもチェックします。 00000111222333000111222333000111222333 ************************************* -------------------------------------× [↑全パターン失格したので次へ] 00000111222333000111222333000111222333 ** --●× …省略 00000111222333000111222333000111222333 *********** -----------●●●●●●●●●●●●●●●●●●●●●●●●● 制約「ループは2回以上繰り返している事」について 最後に以下のようなパターンを想定してみます。 0000011122233300011122233300011122233300 前項のサンプルに加えて、パターンの最後がループの最後ではないケースです。 この場合、今回の「最後まで失格しなかったらループとみなす」ロジックだと 「長いパターンを持ち、配列内に1つしか現れないループ」 として検出されてしまいます。 0000011122233300011122233300011122233300 ************************************** --------------------------------------●● そのため、今回のロジックでは制約として ループは2回以上繰り返している事が必要 なのです。 実際のコード やっとここに来ました。最初にTL:DRしといてよかった。 //ループ検出 for ( // A let loopStartIndex = 0; loopStartIndex < pattern.length; loopStartIndex++ ) { length: for ( // B let loopFrameLength = 2; loopFrameLength < pattern.length / 2; loopFrameLength++ ) { for ( // C let checkIndex = loopStartIndex + loopFrameLength; checkIndex < pattern.length; checkIndex++ ) { const org = ((checkIndex - loopStartIndex) % loopFrameLength) + loopStartIndex; if (pattern[org] !== pattern[checkIndex]) continue length; //D } // E return { start: loopStartIndex, end: loopStartIndex + loopFrameLength - 1 }; } } return null; //F A -- 開始点をずらす B -- チェックするパターンの長さを変える C -- 実際にループの中身をチェックする という流れになっています。 B の繰り返しが pattern.length / 2 になっているのは、「ループは2回以上繰り返している事」 を満たすためです。配列の半分の長さまでチェックして合格しなかったら、そのパターンは失格とみなします。 D は失格ルートなので、B に戻ってやり直します。失格しなかった場合は E に入り、ループ情報を返します。 E に入らずに全ループが終了したという事はループ検出が出来なかったという事なので、今回は null を返します。(F) さいごに ちょっとループ検出ロジックの説明が分かりにくかったかもしれませんね… 僕が想定できていないケースで不具合があるかもしれませんが、とりあえず今回僕が使用したケースではこのロジックでうまく検出できました。 同じような事で参考を探している方のお役に立てれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Prisma導入メモ

概要 prismaの導入から簡単なクエリー・メモ prismaとは node.jsとTypescriptのORマッパーで(Goでも使える)以下の特徴などがある - データモデルをスキーマで表現する - スキーマから型を生成できる(直感的に扱えるようになる) - PRISMA STUDIOという名のSQLクライアントを内臓している(web) セットアップ # インストール $ npm i -D prisma # 初期化 $ npx prisma init 初期化すると以下のファイルが生成される .env prisma/schema.prisma .envにはDBの接続先設定を設定し、schema.prismaのdatasource.providerには、使用するデータベースをしていする(postgresql, mysql, sqliteなど) 公式Doc DATABASE_URLの設定例 # postgresql # postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" # mysql # mysql://USER:PASSWORD@HOST:PORT/TABLE_NAME DATABASE_URL="mysql://root:root@localhost:3306/test_database" # sqlite # file:FILE_PATH DATABASE_URL="file:./dev.db" prisma/schema.prismaにはデータベースの情報やデータモデル(テーブル構造)を記述する ・データベースの情報 ・データモデル ・スキーマ リファレンス マイグレーションの作成・実行 マイグレーションの作成・DBへ反映・型情報の生成 $ npx prisma migrate dev # マイグレーションの語尾に`init`を付与する # `20210606142525_init` # $ prisma migrate dev --name init 他のコマンド # Prisma Studioの起動 $ prisma studio # データベースをリセットしDBへ反映(本番では使用しない) $ prisma migrate reset # マイグレーションのステータスチェック $ prisma migrate status # マイグレーションの実行・DBへ反映 $ prisma migrate deploy # 型情報の生成 $ prisma generate
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む