简体   繁体   English

Javascript async等待等待mongoose等待

[英]Javascript async await not waiting for mongoose await

I am trying to move database calls out of my controller to clean things up and make them testable. 我试图从我的控制器中移出数据库调用来清理并使它们可测试。 When they are in the controller, everything moves smoothly. 当他们在控制器中时,一切都顺利进行。 I moved them out of the controller and added an async to ensure that we wait. 我将它们移出控制器并添加了异步以确保我们等待。 Otherwise, I would call the res.render() function within the .exec() of Users.findOne() . 否则,我会打电话的res.render()的函数内.exec()Users.findOne() Now, once I am using async/await, the function in my controller thinks that there is no user because it is not waiting. 现在,一旦我使用async / await,我的控制器中的函数认为没有用户,因为它没有等待。

There are several questions on SO regarding async await, but I did not find one that resolves my issue. 有关异步等待的SO有几个问题,但我没有找到解决我的问题的问题。 I did verify that my User is returned, and I added console logs to show the path. 我确实验证了我的用户已退回,并且我添加了控制台日志以显示路径。

  • node mongoose async await seemed promising, but their actual problem was failure to return the item, and mine returns fine 节点mongoose async await似乎很有希望,但他们的实际问题是未能返回该项目,并且我的返回正常
  • async not waiting for await is an issue with kotlin 异步不等待等待是kotlin的一个问题
  • async await not waiting Seems very applicable, but I do not understand fully the answer about nested await/async - the problem the asker had was more complicated than my query because they are dealing with loops and forEach async等待不等待似乎非常适用,但我不完全理解嵌套await / async的答案 - 提问者的问题比我的查询更复杂,因为他们正在处理循环和forEach
  • Javascript async await is spot on, so I checked that the mongoose function returns a promise. Javascript async await是spot on,所以我检查了mongoose函数返回一个promise。 Mongoose docs show that it is ready for async because calls return a promise. Mongoose文档显示它已准备好进行异步,因为调用会返回一个promise。

Assume we are resolving the route /users 假设我们正在解决路线/users

routes/index.js 路线/ index.js

// requires & other routes not shown 
router.get('/users', controller.testUserShow);

controllers/index.js 控制器/ index.js

// requires & other routes not shown 
   exports.testUserShow = async (req, res, next) => {
      if (req.user) { // if code to get user is right here, with no async/await, the user is found and the code continues
        try {
          found = await services.fetchUser(req.user._id)
          console.log("I am not waiting for at testusershow")
          console.log(found); //undefined
          // go on to do something with found
        } catch(e) {
          throw new Error(e.message)
        }
      }
    }

services/index.js 服务/ index.js

const db = require('../db')
exports.fetchUser = async (id) => {
  try {
    console.log("fetchUser is asking for user")
    return await db.returnUser(id)
  } catch(e) {
    throw new Error(e.message)
  }
}

db/index.js DB / index.js

const User = require('../models/user');
exports.returnUser = async (id) => {
  User.findById(id)
      .exec(function(err, foundUser) {
          if (err || !foundUser) {
              return err;
          } else {
              // if this was in the controller 
              // we could res.render() right here
              console.log("returnUser has a user");
              console.log(foundUser); // this is a User
              return foundUser;
          }
      });
}

The console log goes 控制台日志

fetchUser is asking for user
I am not waiting for at testusershow
undefined
returnUser has a user
// not printed... valid user 

I would expect the initial call to be undefined if I was calling something that did not return a promise, but User.findOne() should. 如果我调用的东西没有返回一个promise,我会期望初始调用是未定义的,但User.findOne()应该。

What am I missing here? 我在这里错过了什么?

This is the simplest way: 这是最简单的方法:

const User = require('../models/user');
exports.returnUser =  (id) => {
   return User.findById(id).exec().then(foundUser => { 
          console.log(foundUser); // this is a User
          return foundUser;
  });
}

if you want to use async/await then you can do: 如果你想使用async / await那么你可以这样做:

    exports.returnUser = async id => {
       const foundUser = await User.findById(id).exec();
       console.log({foundUser});
       return foundUser;
      });
    }

and if you wanted to use callbacks, it would look like: 如果你想使用回调,它看起来像:

exports.returnUser =  (id, cb) => {
   return User.findById(id).exec(cb);
}

the cool think about Mongoose is that if you don't pass a callback it will return a promise from the exec function/method. 很酷的想想Mongoose就是如果你没有传递一个回调,它会从exec函数/方法返回一个promise。

Your db/index should be like this: 你的db/index应该是这样的:

exports.returnUser = (id) => {
  return User.findById(id);
}

When you don't call exec, it will return a promise. 当你不调用exec时,它将返回一个promise。 And as your services/index.js already uses await to get the response, db/index doesn't need to be an async function. 并且由于您的services/index.js已经使用await来获取响应,因此db/index不需要是异步函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM