首页 > 解决方案 > NodeJs 异步库:为什么发生错误后没有触发回调?

问题描述

我一直在开发 NodeJS 服务器的后端,该服务器当前使用库“async”和“mysql”。请注意,这三个例程在 async 的“瀑布”函数中执行。它应该按如下方式工作:

不幸的是,即使服务器的 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
}

标签: mysqlnode.jsasynchronouscallback

解决方案


推荐阅读