だら$ちっぷす

仕事の覚書です

Node.js postgreSQL ブラウザでSQL文を入力してデータを取得する

★2019-12-18
  asyncを調べたので、fetchの部分をasyncで書き直す
  (メモ)XMLHttpRequestの後fetchが流行ったがfetchはpromiseで値を返して
      くるとか。
      promiseは同期処理を実現するものらしいが、
      thenの中をその関数から帰って来た時に実行することを約束して、
      処理はそこで止まることなく、次の行へと進む
      なので例えばファイル全部読み込むまでそこで止まってて欲しいとき
      なんかには使えない
      それを実現できるのがasyncとawait
      関数をasync宣言しておくと、その中でawaitが使えるようになる
      で、非同期でするする返ってきてしまうやつをawaitで返事が返って
      くるまで止めておくことができる
      ・・・・と、いうことのようです。間違ってたらごめん
      そうそう!こういう風に書きたかってん!感、満載。

【サーバ側】

const express = require('express');     //expressモジュールを読み込む
const app = express();                //expressアプリを生成する

//appでjson送る時はこの2つが必要
//※前はbody_parserってやつをinstallする必要があったが今はexpress標準搭載らしい
app.use(express.json());                        
app.use(express.urlencoded({ extended: true }));

//--------------------------------------------------------
// データベース接続
//--------------------------------------------------------
const {Client} = require('pg');        //pgモジュールを読み込む

const client = new Client(
{
    user: 'postgres',
    host: '127.0.0.1',
    database: 'test',
    password: '',
    port: 5432,
});

client.connect();   //データベースに接続する

//--------------------------------------------------------
// select文を受けて結果を返す
//     ※この部分のURLは自分で決める。決まったものがあるわけではない。
//      ブラウザで「localhost:3000/sql/select/sql文」と叩いたらこれが実行される仕組み。
//--------------------------------------------------------
app.get('/sql/select/:sql',        //:の部分はreq.paramにセットされる
async (req, res) =>              //req はin、resにはoutするデータをセット
                            //これ、なんでいきなり()書くの?ってずっと謎やってんけど、
                            //無名関数やったんか!とasyncでやっと理解した!(´∀`*)
{
    //これはpromiseという記述方式らしい
    //queryの実行が終わってからthenの中身が実行される
    //非同期を順序通りに実行させるために考案された記述方法らしい
    try
    {
        const resq = await client.query(req.params.sql);      //データベースにsqlを投げる
        res.json(resq.rows);        //受け取ったデータをoutパラメータにセット
    }
    catch(err)        //エラーを受け取る
    {
        res.json(["ERROR", err.stack]);    //受け取ったエラーをoutパラメータにセット
    }
});

//--------------------------------------------------------
//     ポート3000でサーバを立てる
//     ※別に3000でなくてもよい。
//      テスト用に3100に変えた同じプログラムを並列して立てたら、
//      それぞれ干渉せずに機嫌よく動いてたんで、なんかそんな感じでw
//--------------------------------------------------------
app.listen(3000, () => console.log('Listening on port 3000'));


★これはfetch覚えたての時のやつ。promise構文を恐る恐る使っている

   client
        .query(req.params.sql)      //データベースにsqlを投げる
        .then(resq =>                //データを受け取る
        {
            res.json(resq.rows);        //受け取ったデータをoutパラメータにセット
        })
        .catch(err =>              //エラーを受け取る
        {
            res.json(["ERROR", err.stack]);    //受け取ったエラーをoutパラメータにセット
        });


【ブラウザ側】

<!DOCTYPE html>
<html>
<head> 
    <meta charset="UTF-8">   
    <title>SQL発行</title>
</head>
<body style="font-size:12px;">
    SQL(select文に限る)
    <input type="text" id="id_sql" style="width:100%">
    <button onclick="click_exec()">SQL実行</button>
</body>

<script>
    async function click_disp()
    {
        const sqlstr = id_sql.value;
        if(sqlstr == "")
            return;   //文が入力されてなかったら終了

        //入力されたSQL文をサーバに送り結果を受信する
        try
        {
            const res = await fetch('./sql/select/' + sqlstr);   //結果受信
            const data = await res.json();
            
            //結果がエラーだった場合
            if(data.length == 2 && data[0] == "ERROR")
            {
                document.write("[DBERROR] ");
                document.write(data[1]);        //エラーの内容を表示
            }
            //結果が成功だった場合
            else
            {
                //結果はレコードの配列で送られてくる
                for(let i = 0; i < data.length; i++)
                {
                    for(let key in data[i])
                        document.write(data[i][key] + ",");
                    document.write("<BR>");
                }
            }
        }
        catch(err)
        {
            document.write("[FETCH ERROR]");
            document.write(err);
        }
    }
</script>

</html>


★これはfetch覚えたての時のやつ。promise構文を恐る恐る使っている

       //入力されたSQL文をサーバに送り結果を受信する
        fetch('./sql/select/' + sqlstr)
        .then
        (
            //結果受信
            response => response.json()
        )
        .then
        (
            data => 
            {
                //結果がエラーだった場合
                if(data.length == 2 && data[0] == "ERROR")
                {
                    document.write(data[1]);        //エラーの内容を表示
                }
                //結果が成功だった場合
                else
                {
                    //結果はレコードの配列で送られてくる
                    for(let i = 0; i < data.length; i++)
                    {
                        for(let key in data[i])
                            document.write(data[i][key] + ",");
                        document.write("<BR>");
                    }
                }
            }
        );