无法理解回调在 Connect 模块中的作用

cannot understand what callback does in a Connect module

我正在阅读一本关于 NodeJs Connect 的书。关于 basicAuth 模块有这个小部分。我知道 basicAuth 现在已被弃用,但我无法理解这个简单的代码。书上说

Providing an asynchronous callback function

The final option is similar, except this time a callback is passed to basicAuth() with three arguments defined, which enables the use of asynchronous lookups. This is useful when authenticating from a file on disk, or when querying from a database.

Listing 7.7. A Connect basicAuth middleware component doing asynchronous lookups

并且没有其他信息。这就是关于在 basicAuth

中进行回调的全部内容

因此,代码获取了用户名和密码。然后假设的对象 User 有一个方法 authendicate 检查这个用户是否真的存在。完成后,调用 gotUser 函数。 gotUser 包含返回的错误(=未找到具有该 username/password 的用户)或返回的用户对象(找到具有该 username/password 的用户)。我说得对吗?

gotUser检查是否有错误。如果存在,returns 并使用错误参数调用 callback。那么等等,此时 callback 会做什么?它没有在任何地方定义。它会将错误传递给错误处理函数吗?又如何?

如果没有错误,gotUser 再次调用 callback null(= 没有错误)和 user。再一次,回调会做什么?为什么将返回的用户传递给回调而不获取其姓名、邮件、年龄等并在会话中使用它们或填充标签的 innerHTML 或其他内容?

谢谢

发生了几件不同的事情。其一,app.use 期望一个将使用 req、res 和 next 调用的函数。当你运行connect.basicAuth时,它运行就是这个方法。

由于这是一个中间件方法,每次命中此方法之后定义的路由时,此方法都会运行。

第二件事是 connect.basicAuth 是一个将使用用户名、密码和回调方法调用的函数。回调是 connect.basicAuth 提供的东西。

如果您 return 回调(错​​误),它将向客户端发送回 401 未授权。如果你 return callback(null, user),它将继续直到下一个中​​间件函数或适当的路由。

So wait, what will callback do at this point? Its not defined anywhere.

callback 的值由 basicAuth 中间件定义。

你可以在basic-auth-connect module, used by connect, in the module's index.js中找到它的定义:

callback(user, pass, function(err, user){
  if (err || !user)  return unauthorized(res, realm);
  req.user = req.remoteUser = user;
  next();
});

gotUser() 调用 callback(...) 时,它从上面的代码片段中调用 function(err, user){...},将 err and/or user 传递给被使用。


并且,在您想知道的两种情况下,它们是如何使用的...

gotUser checks if there is an error. If there is, returns and calls callback with an error argument. So wait, what will callback do at this point?

If there is not an error, gotUser calls callback again with null(= no error) and user. Once again, what will callback do?

两者的if (err || !user)条件都将通过(一个有错误,另一个缺少用户)。然后它会考虑请求 unauthorized 并将立即结束响应。

function unauthorized(res, realm) {
  res.statusCode = 401;
  res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
  res.end('Unauthorized');
};

Why pass the returned user to the callback and not grab its name, mail, age etc etc and use them on a session or fill the innerHTML of a tag or whatever?

中间件正在应用separation of concerns,保持自身尽可能小和简洁。它的目标只是确定一个 req.user 并验证它。

成功完成后,应用程序队列中的其他中间件将能够引用找到的 user。这可以包括使用它从视图中呈现标记:

// determine the user
app.use(connect.basicAuth(...));

// now make use of it
app.use(function (req, res, next) {
  viewEngine.render('view', { user: req.user }, function (err, result) {
    if (err) return next(err);

    res.setHeader('Content-Type', 'text/html');
    res.end(result);
  });
});

注意:这是通用的,不会 运行 按原样。您需要找到并设置您选择的视图引擎并将其替换到代码段中。


此外,关于...的旁注

fill the innerHTML of a tag

虽然 Node.js 正在执行 JavaScript,但它是在自己的环境中执行的,完全脱离任何浏览器。无法与用户当前看到的 DOM 直接交互。