回调如何访问方法

How Callbacks access Methods

我想知道我们如何在回调中使用 res.render

function getUsers(cb){
  fs.readFile('data.json', 'utf8', (err, data) => {
    if (err) return cb(err);
    const users = JSON.parse(data);
    return cb(null, users);
  });
}

app.get('/', (req,res) => {
  getUsers((err,users) =>{
    if(err){
      res.render('error', {error:err})
    } else{
      res.render('index', {title: "users", users: users.users});
    }
  })
}); 

因为当我们传递回调时,Callstack 加载了 getUsers(cb) 函数,而我们不再在路由内部,那么回调是如何使用 res.render 方法的? 我怎么知道向前推进,回调可以访问哪些值?

内联 functions/callbacks 就像您在此处使用的那样可以看到父函数作用域及其所有变量和参数。这被称为“词法范围”。

如果回调不是内联的,那么它就看不到那些 variable/arguments 因为函数将在不同的范围内声明。

因此,这就是为什么您声明的 readFile() 的内联回调可以访问 cb(...) 以及为什么您传递给 getUsers() 的内联回调可以访问 reqres。这些都是父作用域中的参数。

请注意,对这些父级 variables/arguments 的访问并非来自调用堆栈。这是来自 lexical scope.


这种对 res.render() 的访问才有效,因为该函数是在 res 可访问的词法范围内声明的。如果您的路线是这样声明的:

function getUsersCallback(err, users) {
    if(err){
      res.render('error', {error:err})
    } else{
      res.render('index', {title: "users", users: users.users});
    }
}

app.get('/', (req,res) => {
  getUsers(getUsersCallback);
}); 

那么这将不起作用,因为回调函数没有在可以访问 reqres.

的词法范围内声明

请记住,Javascript 中的函数参数和局部变量存储在作用域对象中,而不是像在 C/C++ 这样的语言中那样存储在调用堆栈中。这是出于多种原因,其中最重要的是函数作用域的生命周期可能会超出函数 returns 时(由于闭包),因此可以链接作用域,以便解释器可以在中查找内容父作用域(为了实现语言实现的“词法作用域”)。