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

Pass variable between app.method callbacks in Express

我正在尝试从我的数据库中获取一个记录集并将其存储在一个变量中,以便我可以在随后的呈现视图的回调中使用它。我已经尝试在 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 上创建了一个 属性,但我似乎无法让它工作要么。

我做错了什么?

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
            });
        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 
        });
    });
},

还要检查错误:

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 
        });
    });
},

更新

一些解释为什么会发生。当你 运行 这样的电话时:

x('something');
asyncFunction(args, function (err) {
  y();
});
z();

实际发生的是:

  1. 运行 x() 有一个参数
  2. 运行 asyncFunction() 有两个参数(其中一个恰好是一个函数,但尚未调用 - 只是作为参数传递)
  3. asyncFunction() 内部可能会安排一些异步操作并保存匿名函数以供稍后调用,并且 asyncFunction() returns
  4. 运行 z() 不带参数
  5. 稍后异步操作完成,之前保存的匿名函数现在是 运行
  6. 匿名函数运行s y()

查看此答案,我在其中更详细地解释了此类情况下的执行顺序和控制流程: