我一直在开发NodeJS服务器的后端,该服务器当前使用库'async'和'mysql'。请注意,这三个例程是在异步的“瀑布”功能内执行的。它应如下工作:
不幸的是,尽管服务器的MySQL客户端尝试插入重复的副本,但我使用mocha进行的每个测试仍然通过。
我已经阅读了“异步”库的文档。它说,如果在执行“瀑布”功能期间发生错误,则控制流将重定向到“瀑布”回调。我还尝试查阅“ mysql”库的文档。但是我找不到任何可以帮助我解决问题的东西。我应该将可能引发错误的代码放在try-catch块中,还是必须发出特殊的回调?
文件:SqlTagsTest.js
var mysql = require('mysql');
var mySqlUtils = require('../../backend/MySqlHandler/MySqlUtils.js');
var mySqlTags = require('../../backend/MySqlHandler/MySqlTags.js');
describe('Create new tag',function(){
var connection = "";
var queryParams = "";
before(function(done){
connection = mysql.createConnection({
host:'myHost',
user:'root',
password:'myPassword',
database:'myDb'
});
queryParams = {
name: 'Tag',
description: 'Description',
parent: 'root',
creator: 'me',
admin: false
};
done();
});
it('should create a new tag inside the database',function(){
mySqlTags.CreateTag(connection,queryParams);
});
文件:MySqlTags.js
var sqlUtils = require('./MySqlUtils.js');
var reflectChanges = require('./MySqlReflection.js');
var async = require('async');
function CreateTag(connection,queryParams){
async.waterfall([
function SetupData(callback){
callback(null,connection,queryParams);
},
sqlUtils.ConnectToDatabase,
sqlUtils.InsertTagIntoDatabase,
sqlUtils.CloseDatabaseConnection
],function(err,results){
if(err)
{
throw err;
}
});
}
function DeleteTag(connection,queryParams,serverResponse){
async.waterfall([
function setupData(callback){
callback(null,connection,queryParams);
},
sqlUtils.ConnectToDatabase,
reflectChanges.DeleteTagEntry,
reflectChanges.GenerateUncategorizedTag,
reflectChanges.UpdateChildrensParent,
sqlUtils.CloseDatabaseConnection
],function(error,results){
if(error){
serverResponse(queryParams,error,false);
}else{
serverResponse(queryParams.name,true);
}
});
}
function EditTag(queryParams,serverResponse){
async.waterfall([
sqlUtils.ConnectToDatabase,
sqlUtils.CloseDatabaseConnection
],function(error,results){
if(error){
serverResponse(queryParams.name,false);
}else{
console.log("No errors!");
serverResponse(queryParams.name,true);
}
});
}
module.exports = {
CreateTag: CreateTag,
DeleteTag: DeleteTag,
EditTag: EditTag
}
文件:MySqlUtils.js
var mySql = require('mysql');
var reflectChanges = require('./MySqlReflection.js');
var async = require('async');
/**
* connects to a MySql database
* @param {connection which will be established} connection
* @param {paremeters which are executed} queryParams
* @param {callback which is required by the async library} callback
*/
function ConnectToDatabase(connection,queryParams,callback){
connection.connect(function(error){
if(error){
console.log(error);
throw error;
}else{
callback(null,connection,queryParams);
}
});
}
/**
* closes an existing connection to the MySql database
* @param { connection which is passed from the previous function } connection
* @param { callback when database connection was successfully closed } callback
*/
function CloseDatabaseConnection(connection,queryParams,callback)
{
connection.end(function(error)
{
if(error){
throw error;
}else{
callback(null,connection,queryParams);
}
});
}
/**
* get all files which will be affected by the particular query
* @param {*} connection
* @param {*} queryParams
* @param {*} callback
*/
function GetAffectedFiles(connection,queryParams,callback)
{
const query = "SELECT Name,Tags FROM Tag";
const params = [];
var affectedRows = [];
connection.query(query,params,function(error,results,fields){
if(error){
return connection.rollback(function(){
throw error;
});
}else{
for(var currRow = 0; currRow < results.length; currRow++)
{
if(results[currRow].Name === queryParams.name){
affectedRows.push(results[currRow].Name);
}
}
}
queryParams.affectedRows = affectedRows;
callback(connection,queryParams,callback);
});
}
/**
* inserts a new tag into the database
* @param { connection which will be passed from the previous function } connection
* @param { field values of the original row } queryParams
* @param { callback called when query was executed successfully } callback
*/
function InsertTagIntoDatabase(connection,queryParams,callback){
const query = "INSERT INTO Tag(Id,Name,Description,Parent,Creator,Admin) VALUES((SELECT UUID()),?,?,?,?,?)";
const params = [queryParams.name,queryParams.description,queryParams.parent,queryParams.creator,queryParams.admin];
connection.query(query,params,function(error,results,fields){
if(error){
throw error;
throw error;
}else{
callback(null,connection,queryParams);
}
});
}
/**
* process chain which allows will be triggered upon tag deletion
* @param { connection which was established between } connection
* @param { queryParameters which will be passed to subroutines } queryParams
* @param { callback which will be called upon termination } callback
*/
function ReflectTagRemoval(connection,queryParams,callback){
async.waterfall([
function SetupPrequisites(callback){
callback(null,connection,queryParams);
},
reflect.DeleteTagEntry,
reflect.UpdateChildrenTag,
reflect.UpdateFileTags,
function PassFurther()
{
callback(null,connection,queryParams);
}
]);
}
function ReflectTagUpdate(connection,queryParams,callback){
async.waterfall([
function SetupPrequisites(callback){
callback(null,connection,queryParams);
},
ConnectToDatabase,
reflectChanges.EditTagEntry,
reflectChanges.EditTagChildrenAfterChanges,
reflectChanges.UpdateFileTagsAfterEdit,
function PassFurther(callback){
callback(null,connection,queryParams);
}
]);
}
function ValidateLoginCredentials(connection,loginCredentials,callback)
{
const query = "SELECT Name,Password FROM User WHERE Name = ? AND Password = ?";
const params = [loginCredentials.username,loginCredentials.password];
connection.query(query,params,function(error,results,fields){
if(error)
{
throw error;
}
callback(null,connection);
});
}
module.exports =
{
ConnectToDatabase: ConnectToDatabase,
InsertTagIntoDatabase: InsertTagIntoDatabase,
ReflectTagRemoval: ReflectTagRemoval,
ReflectTagUpdate: ReflectTagUpdate,
ValidateLoginCredentials: ValidateLoginCredentials,
CloseDatabaseConnection : CloseDatabaseConnection
}