如何正确等待javascript中异步函数的返回?

时间:2019-11-25 19:14:55

标签: javascript express async-await google-signin

我目前正在使用带有React前端和Express后端的Google登录身份验证应用程序,并且目前仍处于验证后端令牌的过程中。此过程的文档显示以下代码以验证令牌:

const {OAuth2Client} = require('google-auth-library');

...

const client = new OAuth2Client(CLIENT_ID);
async function verify() {
  const ticket = await client.verifyIdToken({
      idToken: token,
      audience: CLIENT_ID,  // Specify the CLIENT_ID of the app that accesses the backend
      // Or, if multiple clients access the backend:
      //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
  });
  const payload = ticket.getPayload();
  const userid = payload['sub'];
  // If request specified a G Suite domain:
  //const domain = payload['hd'];
}
verify().catch(console.error);

我已经在自己的项目中实现了此代码:

//verify token
async function verify(token, client) {

  const ticket = await client.verifyIdToken({
    idToken: token,
    audience: keys.google.clientID,
  });

  const payload = ticket.getPayload();
  const userid = payload['sub'];
  const domain = payload['hd'];
  const email = payload['email']
  console.log('User ID: ' + userid);
  console.log('Domian: ' + domain);
  console.log('Email: ' + email);

  var message = '';
  var cookie = {};
  await User.find({email: email}, (error, user) => {
    if(error) {
      message = error;
    } else if (user.length === 0) {
      message = 'this user is not in the database';
    } else {
      message = 'this user is in the database';
      const session = new Session({
        email: email,
        session_token: token
      });
      cookie = {
        email: email,
        session_token: token
      };
      session.save((error, session) => {
        if (error) {
          console.log(error);
        } else {
          console.log('session saved');
        }
      });
      console.log(message);
    }
  });
  return Promise.resolve(cookie);
}

//recieve token id from frontend, verify it, and send session back in response
router.post('/google', (req, res) => {
  const body = req.body.tokenID;
  const client = new OAuth2Client(keys.google.clientID);

  let cookie = verify(body, client).catch(console.error);

  console.log('Cookie:' + cookie);
  return res.send(cookie);
});

当前,当此命令运行时,异步函数中的所有内容都会执行,但是return语句仅返回空的promise对象。我认为我错误地使用了asyncawait,但是我不知道如何正确获取函数,以等待所有工作验证令牌,然后在返回之前更新数据库

不确定这是否有帮助,但是当我调用路由时,控制台会向我显示以下输出:

(我从输出字段中删除了我的个人信息,但假设这些行实际上包含gmail帐户信息)

...
Cookie:[object Promise]
User ID: <GOOGLE ID>
Domian: <DOMAIN>
Email: <USER EMAIL>
this user is in the database
session saved

感谢阅读!

2 个答案:

答案 0 :(得分:1)

由于“验证”函数是异步函数,因此应在调用前添加“等待”。要捕获错误,您只需将其放在try / catch中:

router.post('/google', async (req, res) => {
  const body = req.body.tokenID;
  const client = new OAuth2Client(keys.google.clientID);

  try {
    let cookie = await verify(body, client);
    console.log('Cookie:' + cookie);
    return res.send(cookie);
  } catch(error) {
    // handling error
    console.log(error);
    return res.send("error")
}
});

`

答案 1 :(得分:0)

您正在将异步/等待与基于回调的呼叫混合在一起。我不知道您正在使用的库的内部,但是模​​式应该看起来像这样:

var cookie = {};
try{
    const user = await User.find({email: email});
    if (user.length === 0) {
        console.log('this user is not in the database');
    }
    else {
        console.log('this user is in the database');
        const session = new Session({
          email: email,
          session_token: token
        });

        try{
            await session.save();
            console.log('session saved');
        } catch(err){
            console.log(err);
        }
        return {
          email: email,
          session_token: token
        };
} catch(error){
    console.log(error);
}