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都这么多年了还没火。真的太难驾驭了。

零代码第一步,做个添加数据的服务先。node.js + mysql的更多相关文章

  1. Node.js + MySQL 实现数据的增删改查

    通过完成一个 todo 应用展示 Node.js + MySQL 增删改查的功能.这里后台使用 Koa 及其相应的一些中间件作为 server 提供服务. 初始化项目 $ mkdir node-cru ...

  2. Qt 学习第一步 做计划和确定目标

    接下来開始一步步深入学习Qt. 学习的第一步是整理资料,也就是找书和sample. 逛了一些论坛,推荐以下3本书 1> C++ GUI programming with Qt 4(2nd Edi ...

  3. RabbitMQ代码第一步

    Hello RabbitMQ 终于到了使用.Net连接RabbitMQ的时候了,我们首先新建一个控制台应用程序,在程序包管理控制器中NuGet中下载 RabbitMQ. Install-Package ...

  4. Scrapyd 改进第一步: Web Interface 添加 charset=UTF-8, 避免查看 log 出现中文乱码

    0.问题现象和原因 如下图所示,由于 Scrapyd 的 Web Interface 的 log 链接直接指向 log 文件,Response Headers 的 Content-Type 又没有声明 ...

  5. 菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)

    初学Web端开发,今天是第一次将所学做随笔记录,肯定存在多处欠妥,望大家海涵:若有不足,望大家批评指正. 进实验室后分配到的第一个项目,需要制作一个不确定层级树形菜单的数据接口,对于从来没实战编过程的 ...

  6. Node.js的学习--使用cheerio抓取网页数据

    打算要写一个公开课网站,缺少数据,就决定去网易公开课去抓取一些数据. 前一阵子看过一段时间的Node.js,而且Node.js也比较适合做这个事情,就打算用Node.js去抓取数据. 关键是抓取到网页 ...

  7. 使用Node.js实现数据推送

    业务场景:后端更新数据推送到客户端(Java部分使用Tomcat服务器). 后端推送数据的解决方案有很多,比如轮询.Comet.WebSocket. 1. 轮询对于后端来说开发成本最低,就是按照传统的 ...

  8. 好未来数据中台 Node.js BFF实践(一):基础篇

    好未来数据中台 Node.js BFF实践系列文章列表: 基础篇 实战篇(TODO) 进阶篇(TODO) 好未来数据中台的Node.js中间层从7月份开始讨论可行性,截止到9月已经支持了4个平台,其中 ...

  9. JS一般般的网页重构可以使用Node.js做些什么(转)

    一.非计算机背景前端如何快速了解Node.js? 做前端的应该都听过Node.js,偏开发背景的童鞋应该都玩过. 对于一些没有计算机背景的,工作内容以静态页面呈现为主的前端,可能并未把玩过Node.j ...

随机推荐

  1. mysql之数据库添加索引优化查询效率

    项目中如果表中的数据过多的话,会影响查询的效率,那么我们需要想办法优化查询,通常添加索引就是我们的选择之一: 1.添加PRIMARY KEY(主键索引) mysql>ALTER TABLE `t ...

  2. window下的nginx的安装和使用

    nginx功能之一可以启动一个本地服务器,通过配置server_name和root目录等来访问目标文件 一. 下载 http://nginx.org/en/download.html 下载后安装在你钟 ...

  3. 移动设备分辨率(终于弄懂了为什么移动端设计稿总是640px和750px)

    在我开始写移动端页面至今,一直有2个疑问困扰着我,我只知道结果但不知道为什么 问题1:为什么设计师给的设计稿总是640px或750px(现在一般以Phone6为基准,给的750px) 问题2:为什么我 ...

  4. Java实现Http请求的常用方式

    一.使用Java自带的java.io和java.net包. 实现方式如下: public class HttpClient { //1.doGet方法 public static String doG ...

  5. 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下)

    上一篇文章:https://www.cnblogs.com/cgzl/p/9734083.html 处理数据 嵌套字段 看例子: 我想查看viewer下的repositories.注意里面的edges ...

  6. 微信小程序初体验,入门练手项目--通讯录,部署上线(二)

    接上一篇<微信小程序初体验,入门练手项目--通讯录,后台是阿里云服务器>:https://www.cnblogs.com/chengxs/p/9898670.html 开发微信小程序最尴尬 ...

  7. Java I/O不迷茫,一文为你导航!

    前言:在之前的面试中,每每问到关于Java I/O 方面的东西都感觉自己吃了大亏..所以这里抢救一下..来深入的了解一下在Java之中的 I/O 到底是怎么回事..文章可能说明类的文字有点儿多,希望能 ...

  8. AppBoxFuture(五): 分布式文件存储-Store Everything

      本来本篇是想介绍前端组件化开发用户界面,发现框架还未实现文件存储,原本计划是后续设计开发的,索性把计划提前,所以本篇将介绍基于Raft实现分布式的文件存储引擎. 一. 实现思路   既然是分布式存 ...

  9. Python generator和yield介绍

    Python生成器(generator)并不是一个晦涩难懂的概念.相比于MetaClass和Closure等概念,其较为容易理解和掌握.但相对于程序结构:顺序.循环和分支而言其又不是特别的直观.无论学 ...

  10. JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署

    接上篇<JAVA WEB快速入门之环境搭建>,在完成了环境搭建后(JDK.Tomcat.IDE),现在是万事具备,就差写代码了,今天就来从编写一个JSP WEB网站了解JSP WEB网站的 ...