Nodejs的函数返回值

Nodejs的函数返回值

难道nodejs中的return语句跟c里边的不一样吗?这样:我在一个js文件中写了个函数,用来返回数据库打开后的db对象,内容如下:

console.log("In file db.js")  ;
var mongodb=require('mongodb')
, mongoserver=new mongodb.Server('localhost',27017)
,dbweibo=new mongodb.Db('weibo',mongoserver,{w:-1});
function openedDb(){
console.log("in openedDb function")
 if(dbweibo.serverConfig.connected)
 return dbweibo.db;
 else{
     dbweibo.open(function(err,db){
         if(err)
         return "open db failed";
         else {// console.log(db);
         return db; }
        })
     }
}
module.exports.openedDb=openedDb;

你能看到,在最后一个return语句之前有个log语句,这时显示的内容还是一个极其复杂的db对象。

然后我在routes文件中这样写

var db=openedDb();
console.log(db);

但是这回得到的db确实undefined,我就奇怪了,return之前还是正常的db对象,怎么return之后变成undefined了?难道nodejs的return语句与java和c的return语句不通?他不应该返回那个正常的db对象吗?


12 回复

在Node.js中,异步编程是一个非常重要的概念。你遇到的问题主要源于对异步操作的理解不足。在你的例子中,dbweibo.open() 是一个异步操作,它不会立即返回结果,而是通过回调函数来处理结果。

让我们详细分析一下这个问题,并提供一个改进的示例代码。

问题分析

  1. 异步操作dbweibo.open() 是一个异步方法,它会在后台执行打开数据库的操作,并在完成后调用回调函数。
  2. 同步 vs 异步:在 openedDb() 函数中,你尝试在调用 dbweibo.open() 后立即返回 dbweibo.db,但实际上 dbweibo.open() 的回调函数还没有被执行,因此 dbweibo.db 还未被赋值。

改进的示例代码

为了正确处理异步操作,我们可以使用回调函数或Promises。这里我们使用回调函数的方式进行改进:

// 文件: db.js
console.log("In file db.js");

var mongodb = require('mongodb');
var mongoserver = new mongodb.Server('localhost', 27017);
var dbweibo = new mongodb.Db('weibo', mongoserver, { w: -1 });

function openedDb(callback) {
    console.log("in openedDb function");

    if (dbweibo.serverConfig.connected) {
        callback(null, dbweibo.db);
    } else {
        dbweibo.open(function(err, db) {
            if (err) {
                callback(err, null);
            } else {
                callback(null, db);
            }
        });
    }
}

module.exports.openedDb = openedDb;

使用改进后的函数

在你的 routes 文件中,你需要传递一个回调函数来处理异步结果:

// 文件: routes.js
var db = require('./db');

db.openedDb(function(err, db) {
    if (err) {
        console.error("Failed to open database:", err);
        return;
    }

    console.log("Database opened successfully:", db);
});

解释

  1. 回调函数openedDb 函数现在接受一个回调函数作为参数。当数据库成功打开时,它会调用这个回调函数并传入 null 和数据库对象。如果出错,则传入错误对象。
  2. 异步处理:在 routes.js 中,我们通过传递一个回调函数来处理 openedDb 函数的结果。这种方式确保我们在数据库打开后才继续执行后续逻辑。

通过这种方式,你可以正确地处理异步操作,并避免出现 undefined 的问题。


贴代码的格式有误… 楼主编辑一下吧, Markdown 语法注意一下, 只能这么说了 JS 的 return 因为是在回调函数里执行, 已经不是正常的顺序了 况且 return 也不可能隔着两层函数还能 return 回数据吧

一般按回调函数的逻辑,

var db=openedDb();
console.log(db);

是先执行第一行, 再执行第二行, 但是中间一个回调函数, 比如 IO 操作其实还没执行 所以 console.log 执行的时候, 回调函数还没执行, 所以就没有返回值 等到数据库返回数据之后, return 的内容也就没有被捕获了

说的对啊,这个return在回调函数里不可能将return的只作为openedDb的返回值。那要怎么才能正确得到这个db对象呢?这个异步特性带来的流程控制还真是麻烦啊。

一般是放个函数(马仔)近来,干完了事让马仔把东西带走。

这个是异步回调函数里返回的db对象

还是在用阻塞的思路写Node,该换换思路了

哦,类似于回调函数是吗?

刚开始学习的时候感觉不是很难,但是真的做起东西来就感觉这个异步思想还真不是一时半会能变过来的。

返回值可以在回调函数里面获取,反正只要记好一点,这里面是异步的,它稀里哗啦搞定了,才会调用回调函数

写的麻烦 db一直打开不可以么

我是想,如果打开必然要用到open语句,open语句写在程序中,每次用户访问又会执行open语句,这样的话每次都要打开数据库。

在Node.js中,函数的返回值取决于异步操作的结果。你遇到的问题是因为dbweibo.open()是一个异步操作,而你的openedDb函数却试图同步地返回结果。具体来说,当调用dbweibo.open()时,该函数会立即返回,但数据库连接可能还没有完成,因此你的函数没有等到数据库打开就返回了undefined

示例代码

为了正确处理异步操作,可以使用回调函数或者Promise来管理异步逻辑。下面是两种改进方法:

使用回调函数

// db.js
console.log("In file db.js");
var mongodb = require('mongodb'),
    mongoserver = new mongodb.Server('localhost', 27017),
    dbweibo = new mongodb.Db('weibo', mongoserver, { w: -1 });

function openedDb(callback) {
    console.log("in openedDb function");
    if (dbweibo.serverConfig.connected) {
        callback(null, dbweibo.db);
    } else {
        dbweibo.open(function(err, db) {
            if (err) {
                callback(err, null);
            } else {
                callback(null, db);
            }
        });
    }
}

module.exports.openedDb = openedDb;

// routes.js
var db = require('./db');
db.openedDb(function(err, db) {
    if (err) {
        console.error(err);
    } else {
        console.log(db);
    }
});

使用Promise

// db.js
console.log("In file db.js");
var mongodb = require('mongodb'),
    mongoserver = new mongodb.Server('localhost', 27017),
    dbweibo = new mongodb.Db('weibo', mongoserver, { w: -1 });

function openedDb() {
    return new Promise((resolve, reject) => {
        console.log("in openedDb function");
        if (dbweibo.serverConfig.connected) {
            resolve(dbweibo.db);
        } else {
            dbweibo.open(function(err, db) {
                if (err) {
                    reject(err);
                } else {
                    resolve(db);
                }
            });
        }
    });
}

module.exports.openedDb = openedDb;

// routes.js
var db = require('./db');
db.openedDb()
    .then(db => {
        console.log(db);
    })
    .catch(err => {
        console.error(err);
    });

这两种方法都可以确保在数据库成功打开后返回正确的db对象。

回到顶部