零程式碼第一步,做個新增資料的服務先。node.js + mysql

金色海洋(jyk)陽光男孩發表於2019-04-08

node.js + mysql 實現資料新增的功能。萬事基於服務!

 

增刪改查之新增資料。

優點:只需要設定一個json檔案,就可以實現基本的新增功能,可以視為是零程式碼。

 

新增資料的服務實現的功能:

1、  新增一條記錄、多條記錄(批量新增)、主從表記錄

2、  記錄訪問日誌

3、  記錄資料變化記錄

4、  執行步驟跟蹤和計時

5、  異常日誌

6、  許可權判斷

 

 

步驟:

1、  資料庫設計、建表這類的直接略過,假設有了一張表,我們要往這個表裡面新增資料

2、  根據要新增的欄位,設定一個json檔案,對服務進行描述,並且給這個服務設定一個變化,作為區分。

3、  客戶端提交資料和服務變化。

4、  伺服器端,獲取資料和服務變化,呼叫對應的程式進行處理。

5、  處理完畢後處理返回給客戶的資訊

6、  如果有特殊業務需求,可以用外掛的方式來實現。

7、  完成

 

第一步,不管用什麼方式做專案,都是要做的。

第二步需要弄一個json檔案,這個可以自動生成,不用手寫

第三步相當於做一個路由,路由規則制定好了就不用再寫程式碼了。

第四步由框架完成,不需要寫程式碼

第五步判斷一下是否成功,按照規則給瀏覽器返回資料,也不用一遍一遍寫。

第六步不是必須的,大部分的增刪改查都是不需要外掛的。

所以,基本上做一個json檔案,就可以搞定一個服務。需要寫的程式碼無限接近零程式碼。而json檔案又可以自動生成。

 

下面是json檔案的例子:(這個可以自動生成)

 

{
  "operationMode":"add",
  "pluginBefore":"",
  "pluginAfter":"",
  "tableInfo":{
    "tableName": "node_user",
    "primaryKey":"id",
    "sql": "INSERT INTO node_user(id,name,age) VALUES(0,?,?)" ,
    "sqlSelect": "SELECT * FROM node_user WHERE id = ?" ,
    "column":["name","age"]

  } 

}

 

 

然後再說一下程式碼型別,可以分為兩類——框架類和專案類

像.net框架、ado.net、express這類,內部的實現程式碼都是屬於框架級的,內部有再多的程式碼,也不應該算到專案裡面。

而呼叫類庫、使用框架實現專案的程式碼,才是專案級的程式碼,才算作程式碼量。

 

這個要先說清楚,然後再發後面的程式碼。

 

http的使用,屬於專案級的,http的內部實現,就是框架級的。

同理,新增服務的呼叫部分屬於專案級的,服務內部的實現程式碼屬於框架級的。

 

先不上http了,寫一個簡單的測試用程式碼,優點是不用開啟瀏覽器就可以進行測試。要不然每次都要開啟瀏覽器,太麻煩了。

這個不是正式的程式碼,僅僅是初期測試用的。這個是專案級別的程式碼。

/**
 * Created by jyk00 on 2019/3/31.
 * curd的服務
 */

//測試新增服務

//精確計時
var time = require('../preciseTime').time;
//建立新增服務物件
var service = require('./serviceAdd');

var trace={
    title:'收到一個請求:100',
    msg:'',
    startTime:time(),
    endTime:0,
    useTime:0,
    items:[]
};

service.start(100,trace,function (err,info) {

    msg.endTime = time();
    msg.useTime = time() - msg.startTime;

    console.log('完成服務:'+JSON.stringify(trace));

});

 

 

 

 

新增服務的程式碼(業務層) 框架級程式碼

/**
 * Created by jyk00 on 2019/3/31.
 * 新增資料的服務
 */


exports.start = function(code,trace,callback) {
    //精確計時
    var time = require('../preciseTime').time;

    var traceAdd = {
        title:'開始新增資料的服務',
        msg:'',
        startTime:time(),
        endTime:0,
        useTime:0,
        items:[]
    };

    trace.items.push(traceAdd);

    /** 根據配置資訊實現新增資料的功能
     * 獲取服務資訊
     * 接收資料
     * 驗證資料
     * 呼叫外掛
     * 持久化
     * 獲取持久化後資料
     * 寫資料變化日誌
     * 返回結果
     */

    //獲取服務資訊
    //console.log('服務ID:' + code);
    var meta = require('./service_'+ code +'.json');
    console.log('獲取服務資訊:' + meta);

    //獲取實體類,先模擬一下
    var data = require('./node_user.json');

    var info={
        trace:traceAdd,
        requestId:0,
        serviceId:code,
        data:data,
        table:meta.tableInfo
    };

    //驗證資料,暫時略

    //呼叫持久化前的外掛
    var plugName = meta.pluginBefore;
    if (plugName.length === 0){
        //沒有外掛,不呼叫
        console.log('沒有外掛,不呼叫');
        //持久化及後續
        saveAndLast(data);
    }
    else
    {
        //有外掛
        console.log('有外掛,呼叫');
        var plug = require('../plugin/' + plugName);
        plug.begin(data,function(data){
            //持久化及後續
            saveAndLast(data);
        });

    }

    //持久化以及之後的事情
    function saveAndLast(data) {
        //持久化之新增資料
        var db = require('./dataBaseAdd');

        //持久化
        db.query(info,function(err, result){
            console.log('saveData的回撥:' );
            console.log('result:',result);

            //呼叫持久化之後的外掛
            plugName = meta.pluginAfter;
            if (plugName.length === 0){
                //沒有外掛,不呼叫

            }
            else{
                //有外掛
                plug = require('../plugin/' + plugName);
                plug.begin(err, result,data,function() {


                });
            }

        });


    }



};

 

持久化的程式碼(資料層) 框架級程式碼

 

/**
 * Created by jyk00 on 2019/4/1.
 * 資料服務之新增操作
 
 */
//持久化內部的跟蹤
var traceStartAddData = {};
//捕捉異常
process.on('uncaughtException', function (err)  {
    console.log('uncaughtException的trace:' +JSON.stringify(traceStartAddData));
    console.log("捕捉到異常啦");
    console.log(err);

});

exports.query = function(info,callback) {
    //精確計時
    var time = require('../preciseTime').time;

    //持久化之新增資料
    traceStartAddData = {
        title:'持久化之新增資料',
        msg:'',
        startTime:time(),
        endTime:0,
        useTime:0,
        items:[]
    };

    info.trace.items.push(traceStartAddData);

    /** 根據配置資訊實現新增資料的功能
     * 獲取表資訊
     * 接收傳入的資料,驗證任務由上層搞定
     * 持久化
     * 獲取持久化後資料
     * 寫資料變化日誌
     * 返回結果
     */

    //==================獲取表資訊和資料=================================
    var traceGetInfo = {
        title:'獲取表資訊和資料、定義dataChange',
        msg:'',
        startTime:time(),
        endTime:0,
        useTime:0,
        items:[]
    };

    traceStartAddData.items.push(traceGetInfo);

    //獲取表資訊
    var tableInfo = info.table;
    //獲取實體類
    var data = info.data;

    //記錄資料變化情況
    var dataChange = {
        requestId:info.requestId,
        serviceId:info.serviceId,
        tableID:info.table.tableId,
        dataID:0,
        oldDataJson:'',
        newDataJson:'',
        submitDataJson:JSON.stringify(info.data),
        dbResult:'',
        trace:JSON.stringify(info.trace),
        addUserid:1
    };
    traceGetInfo.endTime = time();
    traceGetInfo.useTime = time() - traceGetInfo.startTime;

    //==================建立MySql物件=================================
    var traceCreateMySql = {
        title:'建立MySql物件、cnString、connection',
        msg:'',
        startTime:time(),
        endTime:0,
        useTime:0,
        items:[]
    };
    traceStartAddData.items.push(traceCreateMySql);

    //建立mysql物件
    var mysql  = require('mysql');
    var cnString = require('../sqlConnection.json');
    var connection = mysql.createConnection(cnString);

    traceCreateMySql.endTime = time();
    traceCreateMySql.useTime = time() - traceCreateMySql.startTime;

    //==================傳送持久化請求=================================
    var traceAddNewData = {
        title:'準備傳送持久化請求,新增一條資料',
        msg:'',
        startTime:time(),
        endTime:0,
        useTime:0,
        items:[]
    };

    traceStartAddData.items.push(traceAddNewData);

    var sql = tableInfo.sql;
    //資料轉換成陣列
    var valuesParams = createParams(tableInfo,data);

    myQuery(sql,valuesParams,traceAddNewData,function (err, result) {
        //資料新增完成後的回撥
        //console.log('持久化的回撥的trace:' +JSON.stringify(traceStartAddData));

        if(err){
            console.log('[INSERT ERROR ] - ',err.message);
            traceAddNewData.msg += '_err:' + JSON.stringify(err);
            callback(err, result);
            return;
        }

        //記錄資料變化記錄,
        var log = require('./serviceAdd_11.json');
        //記錄新增資料後的返回資訊
        dataChange.dbResult = JSON.stringify(result);
      
        //從資料庫裡獲取剛新增的資料
        var traceGetNewData = {
            title:'獲取資料庫裡新增完成的資料',
            msg:'',
            startTime:time(),
            endTime:0,
            useTime:0,
            items:[]
        };
        traceAddNewData.items.push(traceGetNewData);

        myQuery(tableInfo.sqlSelect,[result.insertId],traceGetNewData,function (err, result) {
            //獲取一條記錄完畢
            //console.log('獲取更新資料的回撥result:' +JSON.stringify(result));
            //console.log('獲取更新資料的回撥的trace:' +JSON.stringify(traceStartAddData));

            //記錄資料變化日誌
            var traceAddlog = {
                title:'記錄資料變化日誌',
                msg:'',
                startTime:time(),
                endTime:0,
                useTime:0,
                items:[]
            };
            traceGetNewData.items.push(traceAddlog);

            //資料庫裡的新資料
            dataChange.newDataJson = JSON.stringify(result);
            //目前為止的跟蹤記錄
            dataChange.trace = JSON.stringify(info.trace);
            valuesParams = createParams(log.tableInfo,dataChange);

           //提交操作
            myQuery(log.tableInfo.sql,valuesParams,traceAddlog,function (err, result){
                //資料變化日誌回撥完畢
                console.log('資料變化日誌回撥完畢:' +JSON.stringify(info.trace));

            });

        });
        connection.end();

        //回撥,不等資料變化的日誌了
        callback(err, result);

    });

    //console.log('呼叫結束等待結果');

    //封裝資料庫操作,以及計時器
    function myQuery(sql,vParme,traces,callback) {
        //console.log('myQuery的sql:' +sql);
        traces.msg += 'sql:'+sql;
        traces.msg += '_values:' + valuesParams;

        var conn = mysql.createConnection(cnString);
        conn.connect();
        conn.query(sql,vParme,function (err, result) {
            //console.log('myQuery的回撥:' +err);

            traceStart.endTime = time();
            traceStart.useTime = time() - traceStart.startTime;

            if(err){
                console.log('[ERROR ] - ',err.message);
                traceStart.title += '——執行出錯:'+ err.message;
                traceStart.error = JSON.stringify(err)
                callback(err, result);
                return;
            }
            traceStart.title += '——成功!';

            callback(err, result);

        });
        conn.end();
        //請求傳送完畢
        //console.log('請求傳送完畢:');

        traces.endTime = time();
        traces.useTime = time() - traces.startTime;

        //記錄完成開始時間
        var traceStart = {
            title:'請求傳送完畢,等待反饋',
            startTime:time(),
            endTime:0,
            useTime:0,
            items:[]
        };

        traces.items.push(traceStart);
    }

    //拼接valuesParams
    function createParams(colInfo,data){
        //console.log('開始拼接資料陣列');
        var valuesParams = [];
        //資料變成陣列的形式
        var colName = "";
        for (var i=0 ;i<colInfo.column.length;i++) {
            colName = colInfo.column[i];
            valuesParams.push(data[colName]);
        }
       
        return valuesParams;

    }

    //拼接sql
    function createSql2(){
     
        sql = 'INSERT INTO ' +meta.tableName ;

        var cols = "(" + meta.primaryKey;
        var values = " VALUES(0";
        var valuesParams = [];

        //拼接欄位名和引數
        for (var key in meta.cols) {
            cols += ',' + key;
            values += ',?';
            valuesParams.push(meta.cols[key]);
        }
        sql +=cols + ')' + values + ')';
        console.log(sql);

    }

};

 

跟蹤記錄

 

{
    "title": "開始新增資料的服務",
    "msg": "",
    "startTime": 2950080457.323715,
    "endTime": 0,
    "useTime": 0,
    "items": [{
        "title": "持久化之新增資料",
        "msg": "",
        "startTime": 2950080463.596571,
        "endTime": 0,
        "useTime": 0,
        "items": [{
            "title": "獲取表資訊和資料、定義dataChange",
            "msg": "",
            "startTime": 2950080463.608944,
            "endTime": 2950080463.683611,
            "useTime": 0.08490705490112305,
            "items": []
        }, {
            "title": "建立MySql物件、cnString、connection",
            "msg": "",
            "startTime": 2950080463.702811,
            "endTime": 2950080586.696783,
            "useTime": 122.99781227111816,
            "items": []
        }, {
            "title": "準備傳送持久化請求,新增一條資料",
            "msg": "sql:INSERT INTO node_user(id,name,age) VALUES(0,?,?)_values:王五,45",
            "startTime": 2950080586.707023,
            "endTime": 2950080592.260519,
            "useTime": 5.556482791900635,
            "items": [{
                "title": "請求傳送完畢,等待反饋——成功!",
                "startTime": 2950080592.271186,
                "endTime": 2950080612.196954,
                "useTime": 19.944968223571777,
                "items": []
            }, {
                "title": "獲取資料庫裡新增完成的資料",
                "msg": "sql:SELECT * FROM node_user WHERE id = ?_values:王五,45",
                "startTime": 2950080615.264262,
                "endTime": 2950080616.479836,
                "useTime": 1.218986988067627,
                "items": [{
                    "title": "請求傳送完畢,等待反饋——成功!",
                    "startTime": 2950080616.488796,
                    "endTime": 2950080624.55792,
                    "useTime": 8.072536945343018,
                    "items": []
                }, {
                    "title": "記錄資料變化日誌",
                    "msg": "",
                    "startTime": 2950080625.123253,
                    "endTime": 0,
                    "useTime": 0,
                    "items": []
                }]
            }]
        }]
    }]
}

 

我們在寫專案的時候,最鬱悶的就是,執行的時候報錯了,但是又不知道是哪一行出錯了。如果某個函式被呼叫好幾次,那麼就更頭疼了,到底是哪一次的呼叫出錯了呢?

 

有了這個跟蹤就能夠很方便的知道到底是執行到了哪裡出的錯誤,便於定位和修改。

 

ps:

這幾天寫程式碼的感受就是——糟糕透了。怪不得node都這麼多年了還沒火。真的太難駕馭了。

 

相關文章