关于Nodejs 回调函数问题

关于Nodejs 回调函数问题

//dbCon.js

  • var setUser = function () {
  • function callback() {
    
  •     sql.open(conn_str, function (err, conn) {
    
  •         if (err) {
    
  •             console.log("Error opening the connection!");
    
  •             return;
    
  •         }
    
  •         conn.queryRaw("SELECT Username,Password FROM Users", function (err, results) {
    
  •             if (err) {
    
  •                 console.log("Error running query!");
    
  •                 return;
    
  •             }
    
  •             for (var i = 0; i < results.rows.length; i++) {
    
  •                 console.log(results.rows[i][0].toString());
    
  •             }
    
  •             return results.rows[1][0].toString();
    
  •         });
    
  •     });
    
  • }
    
  • return callback();
    
  • }
  • exports.setUser = setUser;

//index.js

  • var users = require(’./dbCon.js’);
  • console.log(users.setUser());

// node index.js the result: return is unfined console.log is ok. 能看懂不。。。求教


13 回复

代码格式化挺重要的,咋就这么不钻业捏~眼睛不好,花呀~编辑框已经提供了常见的样式~


关于Nodejs 回调函数问题

在你的代码中,你尝试通过同步的方式调用一个异步操作(数据库查询)。由于JavaScript的事件循环机制,这种方式会导致无法得到预期的结果。下面我将详细解释这个问题,并提供正确的解决方案。

问题分析

dbCon.js文件中的setUser函数,你定义了一个回调函数callback,并在其中执行了数据库查询。然而,在index.js中,你直接调用了users.setUser(),期望它返回查询结果。这实际上是一个常见的误解,因为在Node.js中,异步操作(如数据库查询)不能直接通过同步方式获取结果。

解决方案

在处理异步操作时,你需要使用回调函数来处理结果。以下是修改后的代码:

dbCon.js

var sql = require('mssql'); // 假设你使用的是mssql库
var conn_str = 'your_connection_string_here'; // 数据库连接字符串

var setUser = function(callback) {
    sql.open(conn_str, function(err, conn) {
        if (err) {
            console.log("Error opening the connection!");
            return callback(err);
        }

        conn.queryRaw("SELECT Username, Password FROM Users", function(err, results) {
            if (err) {
                console.log("Error running query!");
                return callback(err);
            }

            var usernames = [];
            for (var i = 0; i < results.rows.length; i++) {
                usernames.push(results.rows[i][0].toString());
            }

            callback(null, usernames);
        });
    });
};

module.exports = {
    setUser: setUser
};

index.js

var dbCon = require('./dbCon.js');

dbCon.setUser(function(err, usernames) {
    if (err) {
        console.error("An error occurred:", err);
        return;
    }

    console.log("Usernames:", usernames);
});

解释

  1. 回调函数传递:在dbCon.js中,setUser函数接受一个回调函数作为参数。当数据库查询完成时,该回调函数会被调用。
  2. 错误处理:如果在任何步骤发生错误,我们立即调用回调函数并传入错误对象。
  3. 结果传递:成功执行查询后,我们将结果数组传递给回调函数。

这样,你就可以正确地处理异步操作的结果,而不会遇到undefined的问题。

疑问在哪?

他使用了高阶函数,首先外面少了一层函数调用;其次,return的数据到不了外层调用,undefined…闭包、异步及回调原理不太清晰吧^ ^

[@DevinXian](/user/DevinXian) 我也是要测试ajaxIm的demo 才搞一下这个。麻烦求教一下。

        for (var i = 0; i < results.rows.length; i++) {
            console.log(results.rows[i][0].toString());
        }

这有结果吗?

我把你的代码稍微改改,NodeJS菜鸟风格- -正好今天写完年终总结,有点时间~~ 首先是db.js:

var setUser = function (callback) {//callback回调,数据库访问是异步操作,直接return会悲剧
	sql.open(conn_str, function (err, conn) {
    	if (err) {
        	console.log("Error opening the connection!");
        	return callback(err);
    	}
    	conn.queryRaw("SELECT Username,Password FROM Users", function (err, results) {
        	if (err) {
            	console.log("Error running query!");
            	return callback(err);
        	}
        	for (var i = 0; i < results.rows.length; i++) {
            	console.log(results.rows[i][0].toString());
        	}
        	//return results.rows[1][0].toString();//这里return的是内层函数
        	callback(err, results);//使用回调获取数据,第一个参数表示异常
    	});
	});
};

exports.setUser = setUser;

index.js:

var User = require('./db.js');
User.setUser(function(err, data){
	//handle err...
	//handle data
});//此处传入一个函数作为回调获取结果	

[@hades](/user/hades) 有的。(忙在群里 没及时刷新)楼下的兄弟帮我解决了。thanku all the same

[@DevinXian](/user/DevinXian) 谢谢。。我只想说 你们这年总结太及时了。虽然我没看懂。我研究研究 。。best wishes。

谢谢大家!

[@cnhonker07](/user/cnhonker07) 之前说少了一层调用说错了,代码中return callback()本身就调用了,我没看仔细,sorry,所以[@hades](/user/hades) 打印肯定会有的~

[@DevinXian](/user/DevinXian) @.@其实我只是想说,他的回调没写,就你写的那句。

[@hades](/user/hades) 大哥啊。。你去看看我刚提问的一个问题。。跟这个不是差别很多。。。

从你的描述来看,问题在于你试图在 index.js 中直接调用一个需要异步操作的函数 setUser,这会导致未定义的结果。这是因为 setUser 函数中的数据库查询是异步执行的,而你在调用它时没有处理这种异步性。

解决方案

你可以通过传递回调函数来处理异步操作的结果。以下是修改后的代码示例:

dbCon.js

var setUser = function(callback) {
    sql.open(conn_str, function(err, conn) {
        if (err) {
            console.log("Error opening the connection!");
            return callback(null);
        }

        conn.queryRaw("SELECT Username,Password FROM Users", function(err, results) {
            if (err) {
                console.log("Error running query!");
                return callback(null);
            }

            var usernames = [];
            for (var i = 0; i < results.rows.length; i++) {
                usernames.push(results.rows[i][0].toString());
            }

            // 返回结果给回调函数
            callback(usernames);
        });
    });
};

module.exports = {
    setUser: setUser
};

index.js

var dbCon = require('./dbCon.js');

dbCon.setUser(function(usernames) {
    console.log("Usernames:", usernames);
});

解释

  1. 回调函数:在 dbCon.js 中,setUser 函数接受一个回调函数作为参数。当数据库查询完成后,这个回调函数会被调用,并传递查询结果。
  2. 异步处理:在 index.js 中,我们通过传递一个回调函数来处理 setUser 的异步结果。这样可以确保在数据准备好后才进行输出。

通过这种方式,你可以正确地处理异步操作的结果,避免出现 undefined 的情况。

回到顶部