Node.jsの基礎（簡単な操作）


# 環境
Windowsを利用しています。使うエディターはvscodeです。

# インストール

https://nodejs.org/ja/download/

からWindowsの64bit版をインストールします。

# 実行

vscodeでctrl+@でターミナルを開いてターミナル右上の+ボタンの横のプルダウンからcommand promptを選択します。
すると、コマンドプロンプトの操作ができるようになります。

実行したいjavascriptファイル(例えばapp.js)のあるディレクトリまで移動して

```
node app
```

でAPIを実行できます。ずっと動いていたらctrl+cなどで中断してください。

# パッケージの読み込み
フレームワークなどパッケージのインストールが必要な時は以下のようにします。
まず、app.jsを作成して(空でよい)、コマンドプロンプトで

```
npm init
```

と入力します。すると、色々聞かれるので、必要な情報を打ち込みながらEnterを押し続けると次のファイルが生成されます。聞かれた内容もここに記録されています。

```package.json
{
  "name": "tutorial12",
  "version": "1.0.0",
  "description": "tutorial",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "test_usr",
  "license": "ISC"
}
```

例えば、lodashというパッケージが必要な時は、コマンドプロンプトで

```
npm install lodash
```

と入力します。すると、現在いるディレクトリにnode_mojulesというフォルダが生成されてパッケージが保存されます。また、package.jsonとpackage-lock.jsonというファイルも生成されます。

npmコマンドで読み込めるパッケージは

https://www.npmjs.com

で探してみてください。



# 基本操作

## ターミナルに表示

```hello.js
console.log('Hello World from Nodejs');
```

を実行すると、ターミナルに

```
Hello World from Nodejs

```

と表示されます。

## 他のJavascriptファイルの読み込み

```tutorial.js
const sum = (num1,num2) => num1+num2;
module.exports = sum; //sumを他のファイルから読み込めるようにする
```

ここで定義した関数sumをapp.jsで使いたいと思います。

```app.js
const tutorial = require("./tutorial");
console.log(tutorial);
console.log(tutorial(1,1));
```

実行すると

```
[Function: sum]
2

```

と表示されます。出力内容は以下の通りです：
１行目：読み込んだファイルの中身をまとめたobjectを代入した変数tutorialの中身（今回は関数sumだけ）
２行目：tutorial(1,1) の結果

### 読み込む内容が複数ある場合

```tutorial.js
const sum = (num1,num2) => num1+num2;
const PI = 3.14;
class SomeMathObject{
    constructor(){
        console.log('object created');
    }
}
module.exports.sum = sum;
module.exports.PI = PI;
module.exports.SomeMathObject = SomeMathObject;
```

```app.js
const tutorial = require("./tutorial");
console.log(tutorial.sum(1,1));
console.log(tutorial.PI);
console.log(new tutorial.SomeMathObject());
```

出力：

```
2
3.14
object created
SomeMathObject {}

```

## イベントエミッター

https://qiita.com/Apacher-inf/items/8f4a6054eea93650b113

```app.js
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();

eventEmitter.on('tutorial',(num1,num2)=>{
    console.log(num1+num2);
});

eventEmitter.emit('tutorial',1,2);

class Person extends EventEmitter{
    constructor(name){
        super();
        this._name = name;
    }

    get name(){
        return this._name;
    }
}

let pedro = new Person('Pedro');
let christna = new Person('Christina');
pedro.on('name',()=>{
    console.log('my name is ' + pedro.name);
});
christna.on('name',()=>{
    console.log('my name is ' + christna.name);
});

pedro.emit('name');
christna.emit('name');

```

## 対話型のやり取り

```app.js
const readline = require('readline');
const rl = readline.createInterface({  input : process.stdin,
                            output : process.stdout});

//乱数生成した２つの正整数の足し算
let num1 = Math.floor((Math.random()*10)+1);
let num2 = Math.floor((Math.random()*10)+1);
let answer = num1 + num2;

//num1とnum2の和を問う => ターミナルに答えを打ち込む
rl.question(`What is ${num1} + ${num2}? \n`,
(userInput)=>{
    //正解の場合=>終了
    if(userInput.trim() == answer){
        rl.close();
    }
    //不正解の場合=>もう一度解答
    else{
        rl.setPrompt('Incrrect response please try again\n');
        rl.prompt();
        rl.on('line',(userInput)=>{
            if(userInput.trim() == answer){
                rl.close();
            }
            else{
                rl.setPrompt(`Your answer of ${userInput} is incorrect try again \n`);
                rl.prompt();
            }
        })
    }
});

rl.on('close', ()=>{
    console.log('Correct!!!!');
});
```


## ファイル操作

### ファイル生成

```app1.js
const readline = require('readline');
const fs = require('fs');
//create a file
fs.writeFile('example.txt',"this is an example",(err)=>{
    if(err) console.log(err);
    else{
        console.log('File successfully created');
        fs.readFile('example.txt','utf8',(err,file)=>{
            if(err){
                console.log(err);
            }
            else{
                console.log(file);
            }
        });
    }
});
```

実行すると次のファイルが生成されます。

```example.txt
this is an example
```

### ファイル名の変更

```app2.js
const readline = require('readline');
const fs = require('fs');

fs.rename('example.txt','example2.txt',(err)=>{
    if(err) console.log(err);
    else console.log('successfully renamed the file');
});

```

実行すると、先ほど生成したexample.txtがexampl2.txtに変更されます。

### ファイルに書き込み

```app3.js
const readline = require('readline');
const fs = require('fs');

fs.appendFile('example2.txt','Some data being appended',(err)=>{
    if(err) console.log(err);
    else console.log('successfully appended data to file');
})
```

実行するとexample2.txt(元はexample.txt)に分が追加されます。

```example2.txt
this is an exampleSome data being appended
```

### ファイルの消去

```app4.js
const readline = require('readline');
const fs = require('fs');

fs.unlink('example2.txt',(err)=>{
    if(err) console.log(err);
    else console.log('successfully deleted the file');
});
```

## フォルダ操作

### 空のフォルダの生成と消去

```app1.js
const fs = require('fs');
fs.mkdir('tutorial',(err)=>{
    if(err) console.log(err);
    else{
        fs.rmdir('tutorial',(err)=>{
            if(err) console.log(err);
            else{
                console.log('successfully deleted the folder');
            }
        });
    }
});
```

実行するとtutorialというフォルダが生成されて、そのまま削除されます。

### フォルダとその中のファイルの生成

```app2.js
const fs = require('fs');
fs.mkdir('tutorial',(err)=>{
    if(err) console.log(err);
    else{
        fs.writeFile('./tutorial/example.txt','123',(err)=>{
            if(err) console.log(err);
            else{
                console.log('successfully created file');

            }
        });
    }
});
```

実行するとtutorial/example.txtが生成されます。

```tutorial/example.txt
123
```

### フォルダの削除

```app3.js
const fs = require('fs');

fs.unlink('./tutorial/example.txt',(err)=>{
    if(err) console.log(err);
    else{
        fs.rmdir('tutorial',(err)=>{
            if(err) console.log(err);
            else{
                console.log('deleted folder');
            }
        });
    }
})
```

### フォルダ内のファイルの削除

ここではforループでフォルダ内のすべてのファイルを削除します。

```app4.js
const fs = require('fs');
fs.readdir('example',(err,files)=>{
    if(err) console.log(err);
    else{
        for( let file of files ){
            fs.unlink('./example/' + file,(err)=>{
                if(err) console.log(err);
                else{
                    console.log('successfilly deleted file');
                }
            })
        }
    }
});
```

exampleというフォルダにいくつか適当なファイルを入れたうえで実行すると、exampleフォルダの中身が空になります。

## ファイルの複製

```app.js
const fs = require('fs');
const readStream = fs.createReadStream('./example.txt','utf8');
const writeStream = fs.createWriteStream('./example2.txt','utf8');

readStream.on('data',(chunk)=>{
    writeStream.write(chunk);
});
```

## ファイルの圧縮

```app.js
const fs = require('fs');
const zlib = require('zlib');
const gzip = zlib.createGzip();
const readStream = fs.createReadStream('./example.txt','utf8');
const writeStream = fs.createWriteStream('./example2.txt.gz');

readStream.pipe(gzip).pipe(writeStream);
```

## 圧縮ファイルの解凍

```app.js
const fs = require('fs');
const zlib = require('zlib');
const gzip = zlib.createGunzip(); //unzip
const readStream = fs.createReadStream('./example2.txt.gz');
const writeStream = fs.createWriteStream('uncompressed.txt');

readStream.pipe(gzip).pipe(writeStream);
```


いちいち中身を読み込んで書き写していると遅いので、chnckでコピーします。

# 関連記事

https://qiita.com/hiro949/items/67e5586ab82da36c3b78

# 参考記事
- https://nodejs.org/ja/
- https://www.youtube.com/watch?v=RLtyhwFtXQA&list=PLdYSLVEeET--X4dFLv8os6M2V3J2rq97V&index=1&t=3457s&ab_channel=freeCodeCamp.org
- https://nodejs.dev/en/learn/