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

Node.jsとExpressでローカルサーバーを構築する(3) ―JSONを返すスタブAPI―

※ 本記事は、Node.jsとExpressでローカルサーバーを構築する(2) ―Expressでルーティング―の続きです。

最近は、Jsonデータを送りつけたり受け取ったりしてなんやかやするケースが増えてきました。私の極狭い認識の範囲では、フロント側の製作期間中にAPIが完成していないことが多いです。
その為、ローカルサーバーにJSONを返すスタブAPIの機能を実装したいと思います。

スタブとは - IT用語辞典

概要

この記事の概要

  • 目的
    • Node.jsとExpressを利用して、PC上にローカルサーバーを立ち上げる
  • 本記事のゴール
    • GETでリクエストを送ると、JSONデータが返ってくる
    • POSTでJSONデータを送ると、200 OK のレスポンスコードが返ってくる
  • 対象者
    • WEBフロント担当者
    • HTML,CSS,JavaScript(es2015含む)の基本的な構文を理解している人
    • HTTP通信、GET、POSTなどについて、ある程度理解している人(ざっくりで良いです)
    • 黒い画面にコマンドを打ち込むことに抵抗がない方
  • 環境・バージョン
    • Windows10
    • Node.js(推奨版) 10.15.01
    • npm 6.4.1
    • Express 4.16.4
    • Advanced REST client 10.0.12

Chrome拡張ツール:Advanced REST client

GETやPOSTの動作確認を簡単に行うために、Chrome拡張ツールの「Advanced REST client」を利用します。
Advanced REST client
導入方法や利用方法は、下記サイトが詳しいです。分かりやすいUIですので、本記事内でも都度説明します。
「Advanced REST client」の使い方まとめ ~GoogleChromeの拡張ツール

expressでのルーティングの実装

前回のおさらい
Expressを使ったサーバーで、静的コンテンツのルーティングのためにuseメソッドやexpress.staticメソッドを利用しました。

const express = require('express');
const app = express();

app.listen(8080);

app.use(express.static(path.join(__dirname, 'public')));

useは、全てのタイプのリクエストで実行されます。

ルーティングの基本

GETリクエストを受け取る

GETリクエストを受け取りたい場合は、getメソッドを利用します。

// サイトルートへのGETリクエストの場合
app.get('/', (req, res, next)=>{
  res.send('ルートだよ!');
});

// /hoge/fugaへのGETリクエストを受け取りたい場合
app.get('/hoge/fuga', (req, res, next)=>{
  res.send('ほげふが');
});

POSTリクエストを受け取る

POSTリクエストを受け取りたい場合は、postメソッドを利用します。

// サイトルートへのPOSTリクエストの場合
app.post('/', (req, res, next)=>{
  res.send('ルートだよ!全員集合!');
});

// /hoge/fugaへのPOSTリクエストを受け取りたい場合
app.post('/hoge/fuga', (req, res, next)=>{
  res.send('ほげふが');
});

パスの指定

getpostいずれの場合も、第一引数にはピックアップしたいサイト上のパスを指定します。この指定は、ワイルドカードや正規表現などを組み合わせることも可能です。

app.get(/^book/, ()=>{});

上記の例では、/book/booksにはマッチしますが、/boo/ibookとはマッチしません。
公式ガイド:Expressでのルーティング

ミドルウェアの基本

getpostいずれの場合も、第二引数はリクエストを受け取った際のコールバック関数を渡します。このコールバック関数は、ミドルウェア(中間処理を行う関数)と呼ばれます。
ミドルウェアは、リクエストreq・レスポンスresを表すオブジェクトと、後続のミドルウェアへのバトンの役割を果たす関数nextを受け取ります。
このミドルウェア内でクライアントにレスポンスをするか、明示的にプロセスを終了させるかnext()を実行して他へ制御を渡すかしないと、応答なしの状態に陥ってしまいます。

app.get(/^book/, (req, res, next)=>{

  if(req.query.id){
    res.send('OK.');
  }else{
    next();
  }
});

res.send
クライアントへHTTPレスポンスを返すためのメソッドです。
文字列だけでなく、配列やオブジェクトも送信できます。事前に指定しなかった場合、ヘッダーのContentTypeは送信データに応じて自動的に割り当てられます。

res.end
データ送信をせずにレスポンスのプロセスを終了させるためのメソッドです。
実体はNode.jsのコアモジュールhttpresponse.endです。引数にデータを渡せば送信されますが、res.sendなどの専用メソッドを利用する方が望ましいです。

公式ガイド:アプリケーションで使用するミドルウェアの作成

送信されたデータを受け取る

GETで送信されたURLパラメータ

GETで送信されたURLパラメータを受け取るには、ミドルウェアに渡されたreqオブジェクトのqueryプロパティにアクセスします。

/**
 * /search?color=red&size=small へのリクエスト
 */ 
app.get('/search', (req, res, next)=>{

  console.log(req.query.color); // "red"
  console.log(req.query.size);  // "small"

});

リファレンス:req.query(英語)

POSTで送信されたJOSNデータ

POSTでJSONデータを受け取るには、予めパース処理を行うミドルウェアを設定しておく必要があります。このミドルウェアは、Expressに予め用意されています。

const express = require('express');
const app = express();

app.use(express.json()); //パース用ミドルウェアを設定

app.post((req, res)=>{
  console.log(req.body); //パースされたデータを参照
});

Expressの静的メソッドjsonの実行結果をuseメソッドに渡しています。渡すのはあくまでjsonの実行結果として返されるミドルウェアで、jsonメソッドそのものではありません。パースされたデータは、requestオブジェクトのbodyプロパティに格納されます。

リファレンス:express.json(英語)

JSONデータを送る

オブジェクトをパースして送る

オブジェクトをJSONにパースした上で送信したい場合は、res.jsonメソッドを使います。

app.get('/', (req, res, next)=>{
  res.json({ message: `This is a pen.`});
});

リファレンス:res.json(英語)

 JSONファイルを送る

予め用意したJSONファイルを送信したい場合、res.sendFileメソッドが便利です。このメソッドは、Expressのバージョン4.8.0以降からサポートされています。

app.get('/', (req, res, next)=>{
  res.sendFile(__dirname + '/data.json', (err) => {
    if (err) {
      res.sendStatus(400);
    } else {
      console.log('sending completed');
    }
  });
});

第一引数に送信したいファイルの絶対パスを指定します。
第二引数には、送信完了もしくはエラー発生時に呼び出されるコールバック関数を指定します。
エラー発生時はエラー情報を引数で受け取ります。成功時はundefinedです。

リファレンス:res.sendFile(英語)

route()でミドルウェアをまとめる

routeメソッドを利用すると、同一パスに対するタイプ別のリクエストに対し、ミドルウェアを見通し良くまとめられます。

app.route('/moimoi')
  .get((req, res)=>{
    // GET
  })
  .post((req, res)=>{
    // POST
  })
  .put((req, res)=>{
    // PUT
  })
  .delete((req, res)=>{
    // DELETE
  });

リファレンス:app.route(英語)

 Routerでルーティング処理を外部モジュール化する

ルーティング処理を他ファイルで定義して、メインの処理にミドルウェアとして組み込むことが出来ます。

ミドルウェアを定義して公開する

Expressの静的メソッドexpress.Routerを実行してルーティング用のミドルウェアの骨格を生成します。
この骨格に対して、「このパスへのリクエストはこれ返せ」といったルーティング処理を肉付けしていきます。肉付けの方法は、通常のexpress()で取得したオブジェクトと同様に、use、get、post等を利用します。
そして、完成したミドルウェアをエクスポートして公開します。

/**
 *  /api/index.js
 */
const express = require('express');
const router = express.Router(); //ミドルウェアの準備

router.get('/items', (req, res) => {
  res.json({ items: [] });
});

router.post('/registration', (req, res) => {
  res.end('Completed');
});

module.exports = router; //エクスポートして公開

公開されたミドルウェアを利用する

公開されたミドルウェアをインポートしてルーティングに適用します。

/**
 * /app.js
 */
const express = require('express');
const app = express();
const api = require('./api/'); //ミドルウェア読み込み

app.use('/api', api);

/apiへのリクエストの対応を、/api/index.jsで定義したミドルウェアへ渡しています。
この際、ミドルウェア内のルートパスは/apiです。ミドルウェア内で指定した/itemsは、実際は/app/itemsへのリクエストです。ミドルウェア内で/app/itemsとしてしまうと、実際には/app/app/itemsを指定したことになってしまいます。

ガイド:express.Router(日本語)
リファレンス:express.Router(英語)

API機能の実装

上記を踏まえて、API機能を実装していきます。

 ファイルとフォルダの準備

API関連のファイルを格納するフォルダapiを追加します。
このフォルダの配下に、クライアントに送りつけるjsonデータと、ルーティング処理を記述するjsファイルを作成します。

sample/
  ├ public/
  │    ├ css/
  │    │   └ sample.css 
  │    ├ js/
  │    │   └ sample.js 
  │    ├ img/
  │    │   └ sample.png 
  │    └ index.html
  ├ api/
  │    ├ index.js
  │    └ data.json
  └ app.js
/**
 * /app.js
 */
const express = require('express');
const app = express();
const path = require('path');
// /api/index.js で定義されたミドルウェア
const api = require('./api/');

app.listen(8080, () => {
  console.log('Running at Port 8080...');
});

// APIルーティング用ミドルウェアを/apiに設定
app.use('/api', api);

app.use(express.static(path.join(__dirname, 'public')));

app.use((req, res) => {
  res.sendStatus(404);
});


/**
 * /api/index.js
 */
const express = require('express');
const router = express.Router();

// JSONパース
router.use(express.json());

// /api/foo へのGETリクエスト
router.get('/foo', (req, res) => {
  // ファイルを転送
  res.sendFile(__dirname + '/data.json', (err) => {
    if (err) {
      res.sendStatus(400);
    } else {
      console.log('sending completed');
    }
  });
});

// /api/bar へのGET・POSTリクエスト
router.route('/bar')
  .get((req, res) => {

    // 受け取ったパラメータをそのままJSONにして送り返している
    res.json(req.query);
  })
  .post((req, res) => {

    // 必須のデータ項目を、id,name,address として、受信データをチェックしている
    const nameAry = ['id', 'name', 'address'],
      failed = nameAry.some(v => !req.body[v]);

    if (failed) {
      res.sendStatus(400);
    } else {
      res.sendStatus(200);
    }
  });

module.exports = router;

/api/data.jsonに適当な内容を記述します。

{
  "id": "W0001",
  "title": "I Love Cats and Dogs",
  "price": 3000000000000
}

準備が出来たら、サーバーを起動します。

$ node app.js

「Advanced REST client(ARC)」で送受信テスト

送受信のテストを、Chromeの拡張ツールの「Advanced REST client」で行いたいと思います。

こちらから取得できます。
ホーム > アプリ > Advanced REST client

ARCを起動して、まずはTOPページにアクセスしてみます。

  1. Methodを「GET」
  2. RequestURLに「http://localhost:8080/
  3. 「SEND」をクリック

arc.png

「200 OK」とHTMLデータが取得できました。

では、続けてAPIのデータを取得します。
GETで「http://localhost:8080/api/foo」へリクエストを送ると、/api/data.jsonが取得できます。

次は、GETで「http://localhost:8080/api/bar?name=pee&address=poo&age=17」へリクエストを送ります。
URLパラメータの値をJSONで取得で取得できます。

次は、POSTで「http://localhost:8080/api/bar」へリクエストを送ります。

  • 「Parameters>Body>Body content type」を「application/jdon」
  • 「Parameters>Body>Editor view」を「JSON visual editer」
  • id, name, address の三つのプロパティを含むJSONデータを定義

arc02.png

「200 OK」が返ってきました。
次は、項目を一つ減らして送信してみると、「400 Bad Request」が返ってきます。

これで、APIの開発が間に合っていなくても何とかなりそうですね!

初心者の拙い記事を読んでいただき、ありがとうございました。
お役に立てていたら幸いです。

JSON Server

この記事を書いている途中で、JSONを返すAPIを簡単に実現する「JSON Server」なるものの存在を知りました。。。
JSON Server使いこなし - モックサーバーの起動とリソース処理 | CodeGrid
公式:GitHub - typicode/json-server

リンク一覧

  1. Node.jsとExpressでローカルサーバーを構築する(1) ―Node.jsとnpmの導入―
  2. Node.jsとExpressでローカルサーバーを構築する(2) ―Expressでルーティング―
  3. Node.jsとExpressでローカルサーバーを構築する(3) ―JSONを返すスタブAPI―(本記事)
  4. Node.jsとExpressでローカルサーバーを構築する(4) ―他サーバーから画像を取得する―(準備中)

参考情報

Express公式サイト(英語)
Node.js + ExpressでREST API開発を体験しよう[作成編]

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ubuntu+nodejs+express+socketioでサンプルページ

備忘録

目的:herokuへのアップロードのテストをするために、通信のできるサンプルページを作る

やりかた:
virtualboxとubuntuのディスクをダウンロード
仮想マシンを作成、起動
右クリック→端末を起動
下記を順に実行していく

$sudo apt-get install nodejs npm

 //nodejsとnpmをインストールする、バージョンは知らない

$npm install -g express

 //expressをインストールする、バージョンは知らない

$express hoge[任意のフォルダ名]

 //任意のフォルダを作成する

$cd hoge

 //hoge内に移動

$ls hoge

 //hogeフォルダの内容を表示
 //app.js bin package.json public views routes となっていたらOK

$npm install --save socket.io

 //socket.ioをインストール

//いじる場所はviews/index.jadeと、bin/www

bin/wwwの末尾に以下を足す(サーバー側の処理になる)

bin/www(追記)
var io = require('socket.io').listen(server);

io.sockets.on('connection', function(socket) {

  socket.emit('greeting', function (a) {
    console.log('connection clear');
    console.log(a)
  });

  socket.on('client_to_server', function(){
    var tom ='hello';
    console.log('button pushed');
    socket.emit('server_to_client', tom);

  })
});

io.sockets.on('connection')は接続がうまく行ったときにサーバーに送られる'connection'に対して起動している
各処理はこの中に書くと動く

index.jadeを書き換える、テスト用のソースを以下に記載

views/index.jade
doctype html
html
  head
    title Socket.IO Test
    script(src='//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js')
    script(src='/socket.io/socket.io.js')
    script.
      var socket = io.connect();

      socket.on('greeting', function() {
       console.log('hello world')
      });

      function button(){
      console.log('pushed')
      var a=1
      socket.emit('client_to_server',a)
      }

      socket.on('server_to_client', function(tom){
      console.log(tom)
      })


  body
    h1 Socket.IO Test
    input(type='button', onclick='button()', value='叩いてコンソールを出力')

scriptの二行目で、socket.ioを読み込んでいる。詳しいことはわからない。

//いじる

$ npm start

 //自家サーバーを起動、

ブラウザから
http://localhost:3000
を開くと、ページが表示されている

(もし、

Error: Cannot find module 'static-favicon'

とかが出てきていたら、

$ npm install

で、必要なモジュールが全部インストールされる。)

ボタンを押すと各種コンソールが出力される

これをherokuにあげたいぞ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

BOT作成プラットフォームBotpress詳解(1)

Botpresss(1)

弊社ではAIチャットボット・プラットフォーム「バーチャルエージェント」の開発をしています。そのため、オープンソース界ではこの領域でどのようなプロダクトがあるかを調査したりします。その中で、社内で完成度が高い!と話のあがったbotpressについて、調べて行きたいとおもいます。

Botpressとは?

TypeScriptで書かれたオープンソースのBOT作成プラットフォームです。
https://github.com/botpress/botpress

コミットログを見ると開発が始まったのは2016年頃ですね。githubで「bot」というキーワードで検索し、言語をjavascriptで絞り込むと上位に表示されるのでなかなかの注目度なのではないかと思います。今回は下記のデベロッパーズガイドを見ながらどのような機能があるのか概要を見ていきます。
Developer's Guide https://botpress.io/docs/introduction

Botpressの備える機能

下記のような機能を備えていて、botpressを使用すれば簡単にBOTを構築できるようです。

  • NLU Engine
  • Administration dashboard
  • Visual flow editor
  • chat emulator / debugger
  • Support for multiple messaging channels

NLU Engine

watsonやluisなどを使用しなくてもbotpressだけで自然言語理解を行うエンジンを含んでいるようです。どれくらいの精度があるのでしょうか。また日本語はOKなのでしょうか??

Administration dashboard

管理画面ですね。返答に使用するテキストや画像を登録できるようなUIが見受けられますね。
Botpress Studio – WelcomeBot 2019-02-22 08-21-11.png

Visual flow editor

FlowEditorという画面ですが、応答内容や次に質問する内容などをドラッグ&ドロップで作成でき簡単に作成できそうですね!!
Botpress Studio – WelcomeBot 2019-02-22 08-22-16.png

chat emulator / debugger

構築中のbotを試して、期待した応答になっているかチェック/デバッグできる機能のようです。(画面右上にあるアイコンから起動できます)

Botpress Studio – WelcomeBot 2019-02-22 08-27-33.png

Support for multiple messaging channels

Webのチャット用画面からの入力だけではなく、SkypeやSMSからの入力も受け付け可能なようです。SlackはLINE等はどうなのでしょうか。

次回

botpressの11.x系を使用したボットの作成方法や、せっかくのオープンソースですからモジュールの構成や、データ構造について調査していく予定です。

参照

Introduction · Botpress | Developer's Guide https://botpress.io/docs/introduction
参照時は11.5.0のドキュメントでした


We're hiring!

AIチャットボットを開発しています。
ご興味ある方はWantedlyページからお気軽にご連絡ください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxt.js+Express.jsをPleskにデプロイしてみた

Nuxt.jsとExpress.jsで作ったサイトをPleskにデプロイ

Nuxt.jsをPleskにデプロイする情報が少なかったので共有

環境

  • Nuxt.js v2
  • Express.js v4
  • backpack.js
  • Cent OS7
  • Plesk Onyx
  • Node.js v9
  • axios module

1.Nuxt.jsを導入

Nuxt.js

基本的には公式のインストール手順に沿ってやれば大丈夫です。

今回はサーバーサイドフレームワークをExpressに選択
Axios moduleも選択して導入してください。

勝手に環境を作ってくれるのは大分でかい!

2.必要なモジュールをインストール

今回利用するのはbackpack

Nuxt1系のテンプレートでも使われていたやつですね。

これを導入することで、serverの設定時にES6が使えるようになり、build時に起動ファイルを生成してくれます。

下記コマンドで対象のフォルダに追加

yarn add backpack-core

3.package.jsonを編集

Nuxtの起動スクリプトの修正をします。

下記の記述を

package.json
"scripts": {
    "dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
    "build": "nuxt build",
    "start": "cross-env NODE_ENV=production node server/index.js",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint"
},

こちらに変更

package.json
"scripts": {
    "dev": "backpack dev",
    "build": "nuxt build && backpack build",
    "start": "cross-env NODE_ENV=production node build/main.js",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint"
}

これでyarn run buildをしたときにbuildフォルダの下にmain.jsを書き出してくれます。

4.backpackを介してNuxtを起動する設定

backpack.config.jsファイルをフォルダ直下に作成します。

backpack.config.js
module.exports = {
  webpack: (config, options, webpack) => {
    config.entry.main = './server/index.js'
    return config
  }
}

これでNuxt起動時にbackpackが読み込むExpress側の起動スクリプトを読み込んでくれます。

5.Axios moduleの設定

Axiosの設定をしないとルーティングをした際にサーバーエラーがでます。

nuxt.config.jsからaxiosを設定しましょう!

きっとこういうのがあります。

nuxt.config.js
axios: {
    // See https://github.com/nuxt-community/axios-module#options
},

これを自分なりに設定していくんですが、今回は最低限

nuxt.config.js
axios: {
    baseURL: 'https://example.jp/', // ローカルでは必要ない本番環境にデプロイ時設定してください。
    credentials: false,
    browserBaseURL: process.env.BASE_APP_URL || '/'
}

このように設定すれば最低限OK!

6.いよいよデプロイする

gitとかftpなど何でもいいので、pleskの対象のフォルダにnode_modules以外をアップロードしてください。

Pleskの対象のWebドメイン下のNode.jsを有効にしてください。
plesk.png

package.jsonが右側に表示されたら読み込まれている証拠です。

これからやることは

  • まずはNPM installしましょう!
  • Run scriptからbuildコマンドを実行しよう

build.png

ここまで成功したら、Application Startup FileをNuxtフォルダのbuild/main.jsに設定する
これで右側にmain.jsが表示されます。

ここまで来たら、Restart Appを押して再起動します。
これでデプロイが完了です。

起動しない場合は

  • PHP SettingsのPHPが有効になっていないかチェック
  • そもそもbuildができないというときは

https://support.plesk.com/hc/en-us/articles/360000644114-Node-js-Run-Script-option-doesn-t-work-no-node-binary-in-the-current-PATH
ここら辺とか参考にするといいかも

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud Functions を使って Firestore の定期バックアップ

Motivation

Firestore のバックアップを Cloud Scheduler と Cloud Functions で完全サーバーレス的に実行したい。 もちろん、既に先人達が実装済み。

https://tech.ginco.io/post/cloud_scheduler/
https://qiita.com/Kasanomo/items/566191f0c106b4669f22

が、サービスアカウントの秘密鍵を使うようなサンプルになっている。
折角 Cloud Functions 自体が既に権限を持っているのだから、別口で秘密鍵をアップロードする事なくできないだろうかと思って調べてみた。

下準備

コード書く前に環境設定

GCSバケット

まずバックアップ先であるバケットを作成する。 ここでは gs://foo とする。 不特定多数からアクセスされる訳じゃないので Regional でいいだろう。 注意すべきなのは、Firebase のプロジェクト作成時に選択したリージョンと同じにしておくこと。 じゃないと、あとでこける。

IAM

Firebase で Cloud Functions 作った場合のデフォルト権限である <PROJECT_NAME>@appspot.gserviceaccount.com は、Project Editor にもかかわらず、実は十分な権限がついてない。 ということで、Cloud Datastore Import Export Admin のロールとマニュアルで付与する。

Cloud Functions で PubSub トリガーを作る

PubSubの backup-firestore トピックへのメッセージのトリガーにする。

実際のバックアップは googleapis パッケージを使って REST API 呼び出し。 ちなみに、なんだかクセの強いライブラリで、使い方、コード追わないとよくわからんかった。

exports.onFirestoreBackup = functions.pubsub
  .topic('backup-firestore')
  .onPublish(async message => {
    const { google } = require('googleapis')
    const { GCP_PROJECT } = process.env

    const auth = await google.auth.getClient({
      scopes: [
        'https://www.googleapis.com/auth/datastore',
        'https://www.googleapis.com/auth/cloud-platform',
        'https://www.googleapis.com/auth/compute'
      ]
    })

    await google.firestore('v1').projects.databases.exportDocuments({
      name: `projects/${GCP_PROJECT}/databases/${GCP_PROJECT}`,
      requestBody: { outputUriPrefix: 'gs://foo' },
      auth
    })
  })

これで、gs://foo 以下に、2019-02-26T10:10:35_84272/ みたいなディレクトリがバックアップの度に生成されるようになる。 ちなみに outputUriPrefix にバケットを指定する際にバケット名の先(gs://foo/bar)まで指定すると、タイムスタンプのディレクトリが作られず、そのディレクトリ直下にファイルが置かれる仕様っぽい。

謎に https://www.googleapis.com/auth/compute を追加してあげる必要があった。なぜかはよくわからない。きっと内部の話なんだろう。

Cloud Scheduler

GCPコンソールからさらっと設定。 任意のタイミングで backup-firestore トピックへメッセージを投げる。 メッセージの中身は読まないのでなんでもいい。 空メッセージは送れなかったような気がしなくもないので {} とかにした。本当に空でもいいのかもしれない。

設定できたら Run Now で手動実行。

結果

普通にできた。Cloud Functions のログを確認。

リストアするには CLI から
gcloud alpha firestore import gs://[BUCKET_NAME]/[EXPORT_PREFIX]/

これで、また一つ秘密鍵の管理が減った。嬉しい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

node.jsでファイルの入出力操作

はじめに

なんかのコードテストをJavaScript(node.js v10)で受験していた際、ファイルの入出力に関する出題があり、やったことなかったので入出力関連処理だけをまとめました。

ファイル読み込み

node.jsの標準ライブラリfsを用いて実装します。
一般的にファイルの入出力は時間がかかる処理のため、同期処理、非同期処理のメソッドがそれぞれ用意されています。

同期処理メソッド「readFileSync」

要はファイルの読み込みが完了してから、後続の処理を行いたい場合ですね。
JavaやPythonなんかに慣れている人はこちらの方が直感的かと思います。

基本構文は、fs.readFileSync(path[, options])です。

readFileSync.js
const fs = require('fs');
let text = fs.readFileSync("sample.txt");
console.log(text);

node readFileSync.jsとかで実行してみると、ファイルの中身が表示されるかと思います。

文字コードを指定したい場合、第二引数で直接指定するか、オプションオブジェクトとして指定する方法があります。

readFileSync.js
const fs = require('fs');
// 文字コードを直接指定
let text = fs.readFileSync("sample.txt", 'utf-8');
console.log(text);

// 文字コードをオプション指定
let text2 = fs.readFileSync("sample.txt", , {encoding: 'utf-8'});
console.log(text2);

※オプションに指定できるflagについて

ちょっと話が逸れますが、オプションオブジェクトのパラメータはencodingの他にflagがあります。
flagのデフォルトはrで「読み取り用でファイルを開く。ファイルが存在しない場合は例外を発生する」動きになります。
例えば、ここをaとかすると、ファイルが存在しない場合に新規作成してくれたりします。
詳しくは公式ページ[fs_file_system_flags]を参照ください。

非同期処理メソッド「readFile」

要はファイルの読み込みを待たずに後続処理を捌きたい場合です。
基本構文はfs.readFile(path[, options], callback)です。

readfile.js
const fs = require('fs');

fs.readFile("sample.txt", 'utf-8', (err, data) => {
  if (err) throw err;    // 例外発生時の処理
  console.log(data);
});

console.log('ファイル読み込みを待たずに後続処理が走ります。');

非同期で処理を実行するため、以下のように出力されるかと思います。

ファイル読み込みを待たずに後続処理が走ります。
ファイルの中身

ファイル読み込み後に行いたい処理が複雑になればなるほど、コールバック地獄に陥りやすいので注意です。。
Node.js v8.0以降をお使いであれば、util.promisifyでPromise化してあげることも検討してみてください。

ファイル書き出し

こちらもファイルの読み込みと同様、同期処理か非同期処理かでメソッドを使い分けましょう。

同期処理メソッド「writeFileSync」

基本構文はfs.writeFileSync(file, data[, options])です。

writeFileSync.js
const fs = require('fs');
let text = "書き出したい内容";
fs.writeFileSync("output.txt", text);

こちらもreadFileSync同様、オプションの指定ができます。
ファイル書き出しの場合のデフォルトはwで、ファイルが存在しない場合は新規作成してくれますが、ファイルが存在する場合は上書いてしまうので注意してください!

同期処理メソッド「writeFile」

基本構文はfs.writeFile(file, data[, options], callback)です。
書き出した結果の処理(成功した場合にメッセージを出すなど)を実装したい場合はこちらを使うのが良いかと思います。

writeFile.js
const fs = require('fs');
let text = "書き出したい内容";
fs.writeFileSync("output.txt", text, (err) => {
  if (err) throw err;
  console.log('ファイルが正常に出力されました。');
});

おわりに

こういうのは一回使うと忘れがちなので、こまめにまとめてTips化したいなーと思っていますが、なかなか時間なかったり…

参考

公式ドキュメント: Node.js v11.10.0 Documentation
from scratch: util.promisify が追加された

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

グローバルインストールなしで nodemon を使用する

はじめに

Node.jsで開発中、修正が終わるたびに再起動するはなかなかの手間になり、
ストレスがたまります。そこでソース修正後に自動再起動してくれるnodemonの登場です。

nodemonはグローバルにインストールして使われることが多いようですが、
今回はnodemonをローカルインストールで動かす方法を調べてみました。

インストール

$ npm install --save-dev nodemon

この例では開発依存としてインストールしました。
--save-dev の代わりに --save を使用して、通常の依存としてインストールしても問題ありません。

package.jsonを編集

その後、package.jsonを以下のようにを編集します。

package.json
"scripts": {
  "start": "nodemon index.js"
}, 

index.jsは適宜実行したいファイル名に置き換えてください。

サーバーを起動

$ npm start

以上で、ファイル修正後にnodemonが自動で再起動してくれるようになりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ANGULAR.JS公式チュートリアルのPhoneCat Tutorial Appはじめました。

ANGULAR.JS公式チュートリアルのPhoneCat Tutorial Appはじめました。

なぜ始めたのか?

業務でJavascriptのwindowオブジェクトの操作とJasmineのUTをやる機会が
あったので、これを機会にJavaScriptの知識を深めたいと思い、テーマを探していました。

目に留まったのがGoogleなどが開発を手掛けたAngularJSが有名!などという情報が入ってきたので、公式ページにあったチュートリアルを試してみることにしました。
電話のカタログページを使ったチュートリアルみたいですね。

参考:https://docs.angularjs.org/tutorial

ひとまず、今回は環境構築から始めたいと思いまっす。

前提

・Gitがインストールされていることを前提として進めます。

環境構築

繰り返しになりますが、今回は環境構築がメインです。

まずはangular-phoncatのリポジトリをクローンして
クローンしたフォルダをカレントディレクトリにします。

git clone --depth=16 https://github.com/angular/angular-phonecat.git
cd angular-phonecat

--depth=16のオプションは最新16件分のコミットのみ抽出するらしいです。
ダウンロード速度を考慮して設定してるみたいですね。

次に依存関係を解決するためにNode.jsをインストールします。
これは事前設定されているローカルWEBサーバの実施に使うみたいです。

インストーラはOS毎に分かれているので公式ページから適切なものをダウンロードしてインストールしてください。

参考:https://nodejs.org/en/download/

Node.JSについてよくわからなかったので調べてみたところ、サーバでJavaScriptを実行できるようにするための
プラットフォームらしいです。
まずは使ってみて雰囲気つかんでみて、気になるとこがあったら詳細に調べてみたいと思います。

インストールが完了したらコマンドラインで次のコマンドを叩いて正常にインストールされた事を確認します。
ちなみに、2019年2月26日現在ではv10.15.1が推奨される最新のNode.jsです。
11.10.0も公開されていましたが、安定している方を選びます。

node --version

Node.jsをインストールしたらnpmも取得されます。
npmはパッケージ管理ツールでNode.jsのパッケージを管理するのに使用します。
まずは依存関係をインストールしてみます。

npm install

完了したら実際にWEBサーバを起動してみましょう!
デフォルトの設定ではポート8000をリスナーとするlocalhostが作成されるはずです。

npm start

起動に成功したらhttp://localhost:8000/index.htmlにアクセスしてみましょう。
こ、これがAngular.jsを使ったページか!めっちゃカッコいい画面やんけ!って画面が表示されれば成功です。

さて、まだ環境構築は終わりではありません。
次は単体テストの機能が正常に動作するか確認します。

angular.jsはKarmaを使って単体テストするように構築されています。
さっそくKarmaを起動してみます。
起動はnpmの以下コマンドでできます。

npm test

Chromeのブラウザが起動してKarmaの画面が表示されます。
今回はKarumaの勉強に焦点を当てるわけではないので、いったん此処まで。

次にテストツールのE2E(エンドツーエンド)の確認です。
このプロダクトはユーザとブラウザの対話をシュミレートすることでテストします。

WEBサーバが起動した状態で、別のコマンドラインを起動して、次のコマンドを実行します。

npm run protractor

すると、ブラウザが起動してアプリケーションを自動でテストし始めます。
検索用テキストボックスに勝手に文字が入力されて検索されたりと少し驚きますが、これによりE2Eのテストが自動化できる仕組みっぽいです。
たぶん別途specを用意する必要があるんだと思いますが、これは別の機会に勉強します。

今回はここまで!

参考:https://docs.angularjs.org/tutorial/step_01

マークダウンは後程なおします。
おやすみなさい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む