Node.js 在Express中的app.method回调之间传递变量

Node.js 在Express中的app.method回调之间传递变量,node.js,express,request,response,middleware,Node.js,Express,Request,Response,Middleware,我试图从数据库中获取一个记录集,并将其存储在一个变量中,以便在呈现视图的后续回调中使用它。我尝试在req对象上创建一个变量,但在下一次回调中调用它时,它返回为未定义 app.get( '/behaviorchart', authenticated, function(req, res, next) { sql.connect(dbconfig, function (err) { new sql.Request()

我试图从数据库中获取一个记录集,并将其存储在一个变量中,以便在呈现视图的后续回调中使用它。我尝试在req对象上创建一个变量,但在下一次回调中调用它时,它返回为未定义

app.get(
    '/behaviorchart',
    authenticated,
    function(req, res, next) {
        sql.connect(dbconfig, function (err) {
            new sql.Request()
                .input('TeacherID', sql.Int, req.user.UserID)
                .execute('dbo.GetTeacherStudentCards', function (err, recordsets, returnValue) {
                    req.studentCards = recordsets[0] // recordset without return value
                });
            sql.on('error', function (err) {
                // ... error handler 
            });
        });
        next();
    },
    function(req, res) {
        console.log(req.studentCards);
        res.render('behaviorchart.ejs', {
            user : req.user // gets user from session for ejs template
        }); 
    }
);
我读过一些人,特别是在他们的视图中使用变量时,在res.locals上创建了一个属性,但我似乎也无法实现这一点

我在这里做错了什么?

您下一次在这里打电话太早了:

function(req, res, next) {
    sql.connect(dbconfig, function (err) {
        new sql.Request()
            .input('TeacherID', sql.Int, req.user.UserID)
            .execute('dbo.GetTeacherStudentCards', function (err, recordsets, returnValue) {
                req.studentCards = recordsets[0] // recordset without return value
            });
        sql.on('error', function (err) {
            // ... error handler 
        });
    });
    // THIS IS CALLED BEFORE THE DATABASE QUERY FINISHES
    next();
},
试着这样做:

function(req, res, next) {
    sql.connect(dbconfig, function (err) {
        new sql.Request()
            .input('TeacherID', sql.Int, req.user.UserID)
            .execute('dbo.GetTeacherStudentCards', function (err, recordsets, returnValue) {
                req.studentCards = recordsets[0] // recordset without return value
                // CALL NEXT HERE:
                next();
            });
        sql.on('error', function (err) {
            // ... error handler 
        });
    });
},
x('something');
asyncFunction(args, function (err) {
  y();
});
z();
但也要检查错误:

function(req, res, next) {
    sql.connect(dbconfig, function (err) {
        new sql.Request()
            .input('TeacherID', sql.Int, req.user.UserID)
            .execute('dbo.GetTeacherStudentCards', function (err, recordsets, returnValue) {
                // CHECK FOR ERRORS:
                if (err) {
                    return next(err);
                }
                req.studentCards = recordsets[0] // recordset without return value
                // CALL NEXT HERE:
                next();
            });
        sql.on('error', function (err) {
            // ... error handler 
        });
    });
},
使现代化 关于为什么会发生这种情况的一些解释。当您运行这样的呼叫时:

function(req, res, next) {
    sql.connect(dbconfig, function (err) {
        new sql.Request()
            .input('TeacherID', sql.Int, req.user.UserID)
            .execute('dbo.GetTeacherStudentCards', function (err, recordsets, returnValue) {
                req.studentCards = recordsets[0] // recordset without return value
                // CALL NEXT HERE:
                next();
            });
        sql.on('error', function (err) {
            // ... error handler 
        });
    });
},
x('something');
asyncFunction(args, function (err) {
  y();
});
z();
实际情况是:

使用一个参数运行x 使用两个参数运行asyncFunction,其中一个恰好是函数,但尚未调用它-只是作为参数传递 在asyncFunction内部,可以安排一些异步操作,并保存匿名函数以供稍后调用,asyncFunction返回 不带参数运行z 稍后,异步操作完成,之前保存的匿名函数现在运行 匿名函数的运行方式为y 请参阅下面的答案,其中我更详细地解释了此类情况下的执行顺序和控制流:


您是否尝试过console.log记录集?sql是否向db插入了任何数据?是的,但它不是插入。存储过程是select语句。对于我自己的启发,在数据库完成查询之前,next是如何调用的?它位于回调中的sql.connect函数之后。它不是只有在sql.connect函数执行后才会运行吗?@cwanjt请参阅我更新的答案以获得更详细的解释。