零代码第一步,做个添加数据的服务先。node.js + mysql
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的更多相关文章
- Node.js + MySQL 实现数据的增删改查
通过完成一个 todo 应用展示 Node.js + MySQL 增删改查的功能.这里后台使用 Koa 及其相应的一些中间件作为 server 提供服务. 初始化项目 $ mkdir node-cru ...
- Qt 学习第一步 做计划和确定目标
接下来開始一步步深入学习Qt. 学习的第一步是整理资料,也就是找书和sample. 逛了一些论坛,推荐以下3本书 1> C++ GUI programming with Qt 4(2nd Edi ...
- RabbitMQ代码第一步
Hello RabbitMQ 终于到了使用.Net连接RabbitMQ的时候了,我们首先新建一个控制台应用程序,在程序包管理控制器中NuGet中下载 RabbitMQ. Install-Package ...
- Scrapyd 改进第一步: Web Interface 添加 charset=UTF-8, 避免查看 log 出现中文乱码
0.问题现象和原因 如下图所示,由于 Scrapyd 的 Web Interface 的 log 链接直接指向 log 文件,Response Headers 的 Content-Type 又没有声明 ...
- 菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)
初学Web端开发,今天是第一次将所学做随笔记录,肯定存在多处欠妥,望大家海涵:若有不足,望大家批评指正. 进实验室后分配到的第一个项目,需要制作一个不确定层级树形菜单的数据接口,对于从来没实战编过程的 ...
- Node.js的学习--使用cheerio抓取网页数据
打算要写一个公开课网站,缺少数据,就决定去网易公开课去抓取一些数据. 前一阵子看过一段时间的Node.js,而且Node.js也比较适合做这个事情,就打算用Node.js去抓取数据. 关键是抓取到网页 ...
- 使用Node.js实现数据推送
业务场景:后端更新数据推送到客户端(Java部分使用Tomcat服务器). 后端推送数据的解决方案有很多,比如轮询.Comet.WebSocket. 1. 轮询对于后端来说开发成本最低,就是按照传统的 ...
- 好未来数据中台 Node.js BFF实践(一):基础篇
好未来数据中台 Node.js BFF实践系列文章列表: 基础篇 实战篇(TODO) 进阶篇(TODO) 好未来数据中台的Node.js中间层从7月份开始讨论可行性,截止到9月已经支持了4个平台,其中 ...
- JS一般般的网页重构可以使用Node.js做些什么(转)
一.非计算机背景前端如何快速了解Node.js? 做前端的应该都听过Node.js,偏开发背景的童鞋应该都玩过. 对于一些没有计算机背景的,工作内容以静态页面呈现为主的前端,可能并未把玩过Node.j ...
随机推荐
- 多媒体管理器解析IMultimediaManager
一.基本API bool Available { get; } bool Working { get; } AdvancedOptions Advanced { get; } 二.作为通信引擎 str ...
- 微信小程序客服消息开发实战:实时在手机上接收小程序客服消息通知,以及在手机上回复
在微信小程序开发中,可以非常方便的集成客服功能,只需要一行代码便可以将用户引导至客服会话界面.这行代码就是: <button open-type="contact" bind ...
- Java引用详解-StrongReference SoftReference WeakReference PhantomReference
1 Java引用介绍 Java从1.2版本开始引入了4种引用,这4种引用的级别由高到低依次为: 强引用 > 软引用 > 弱引用 > 虚引用 ⑴强引用(StrongR ...
- C# 4.0 的 Visual Studio 2010 示例
C# 4.0 的 Visual Studio 2010 示例 我们将 C# 示例分为两种不同的类别: 语言示例 LINQ 示例 语言示例 语言示例帮助您熟悉各种 C# 语言功能.这些示例包含在 Lan ...
- #Java学习之路——基础阶段二(第七篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- Mac电脑上一款非常时尚高清的动态壁纸Living Wallpaper HD
很多朋友Mac电脑上都喜欢用动态壁纸,Living Wallpaper HD是本人尝试的一款非常不错的高清动态壁纸.有时钟.天气等各种组建,非常时尚美观. Living Wallpaper HD下载地 ...
- Python爬虫入门教程 50-100 Python3爬虫爬取VIP视频-Python爬虫6操作
爬虫背景 原计划继续写一下关于手机APP的爬虫,结果发现夜神模拟器总是卡死,比较懒,不想找原因了,哈哈,所以接着写后面的博客了,从50篇开始要写几篇python爬虫的骚操作,也就是用Python3通过 ...
- django插入数据库错误:mysql的1267错误
错误信息: django.db.utils.OperationalError: (1267, "Illegal mix of collations (latin1_swedish_ci,IM ...
- LindDotNetCore~授权中间件的介绍
回到目录 LindDotNetCore中间件 大叔认识中间件就是主要对http请求进行拦截,然后添加具体个性化功能的逻辑,这种把请求切开,添加新逻辑的方式一般称为面向方面的逻辑AOP! 授权中间件 请 ...
- 104 - kube-scheduler源码分析 - predicate整体流程
(注:从微信公众:CloudGeek复制过来,格式略微错乱,更好阅读体验请移步公众号,二维码在文末) 今天我们来跟一下predicates的整个过程:predicate这个词应该是“断言.断定”的意思 ...