【问题标题】:Wait for the response from an asynchronous function before continuing? [duplicate]在继续之前等待来自异步函数的响应? [复制]
【发布时间】:2018-11-23 16:51:20
【问题描述】:

假设我想在执行任务之前检查登录用户是否具有管理权限。如果我必须等待 mongoose 函数检查数据库以了解用户是否有权限,我该如何异步实现?

假设我有一个这样的用户模型:

  const UserSchema = new Schema({
  username: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  isadmin: {
    type: Boolean,
    default: false
  }
});

然后我创建一个函数来检查用户是否是管理员

function isAdmin(id) {
  let is = false;
  User.findById(id)
    .then(user => {
      if (user) {
        if (user.isAdmin) {
          is = true;
        }
      }
    })
    .catch(err => console.log(err));

  //Now I want to wait for the findById function to resolve before returning this function
  return is;
};

然后假设我想在执行诸如从帖子中删除评论之类的操作之前检查用户是否是管理员

router.delete("/post/comment/:id"),
  (req, res) => {
    if (!isAdmin(req.user.id)) {
      return res.status(401).json({ notauthorized: "User is not admin" });
    }

    //Go ahead and remove content
  }
);

【问题讨论】:

  • 您可以让isAdmin 本身返回一个承诺并将其链接到您的router.delete,或者您可以考虑使用async/await

标签: javascript node.js express asynchronous mongoose


【解决方案1】:

类似于 EQuimper,但使用 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

async function isAdmin(req, res, next) {
  const user = await User.findById(req.user.id).exec();
  if (!user) {
    next(new Error("User not found"));
    return;
  }
  if (!user.isAdmin) {
    res.status(401).json({ notauthorized: "User is not admin" })
    return;
  }
  next();
};

router.delete("/post/comment/:id", isAdmin, (req, res) => {
  // Do something
});

isAdmin 中间件也可以写成:

const isAdmin = async (req, res, next) => {
  const user = await User.findById(req.user.id).exec();
  if (!user) {
    next(new Error("User not found"));
    return;
  }
  if (!user.isAdmin) {
    res.status(401).json({ notauthorized: "User is not admin" })
    return;
  }
  next();
};

【讨论】:

    【解决方案2】:

    您可以在passportjs 中的用户对象或您用于doc 的包中添加管理员密钥。之后,您可以创建一个中间件并在任何路线中随意使用它。如果不看第二个选项。您可以在此中间件中查询用户并检查 admin 是否为 true。希望有意义:)

    const requireAdmin = (req, res, next) {
      if (req.user.admin) {
        return next();
      }
    
      res.sendStatus(401);
    }
    
    // Or you can
    
    const requireAdmin = (req, res, next) {
      User.findById(req.user.id)
        .then(user => {
          if (user.admin) {
            return next();
          }
          res.sendStatus(401);
        }).catch(() => res.sendStatus(401))
    }
    
    
    router.delete("/post/comment/:id"),
      requireAdmin,
      (req, res) => {
        // do logc
    );
    

    【讨论】:

    • 我正在使用 JWT 进行护照身份验证,并在前端进行 React。最初,我将 JWT 有效负载中用户的 isadmin 值发送到 React,并将其包含在 API 请求中,但是我认为仅依靠来自前端的请求来回答用户是否是非常安全的管理员。我是否正确假设在 router.delete 中使用该函数作为中间件将在继续之前等待该函数的结果?
    • 问题是,如果您不想请求,则需要在 jwt 中包含此值是。如果不是,您可以使用内存中的东西等。如果您想添加更多安全性,您可以添加安全性使管理员的令牌快速过期。这些东西将更多地与应用程序相关。但我向你展示的方式是你会在网络上看到很多东西的方式。我认为这是一种标准。但我明白你的意思。
    • 是的,我刚刚实现了Francisco's,它与您在这里的版本略有不同。我大部分时间都不理解中间件在我认为的路由器功能中是如何工作的,但我们现在都被摆平了。
    • 如果您需要帮助理解中间件,这个链接应该可以帮助您。当您使用 express 时,了解它们非常重要。 expressjs.com/en/guide/using-middleware.html希望能帮到你:)
    猜你喜欢
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-17
    • 2021-07-12
    • 2018-04-19
    • 1970-01-01
    • 2020-01-18
    相关资源
    最近更新 更多