почему мой асинхронный ожидание не работает должным образом - PullRequest
1 голос
/ 07 октября 2019

Я работаю над API с экспресс-JS, в моем вызове API я вызвал 2 функции, первая из них login(), а другая функция get_organizations(), но get_organization() вызывается без завершения функции login(), я использовалasync ждут, но он не работает должным образом, кто-нибудь может помочь мне решить эту проблему? Я добавил весь свой код здесь,

router.get('/', async (req, res) => {
    let token = await login();
    await get_organizations(token);
});

const get_organizations = async function (api_token) {
    try {
        console.log('Get List Of Organizations');
        console.log('Verifying token');
        let verify_token_data = await jwt.verify(api_token, config['token-secret']);
        console.log(verify_token_data);
        return false;      
    } catch (error) {
        console.log(error);
    }
}

const login = async function () {
    try {
        console.log('Login process started');
        const newToken = await jwt.sign({login:'login'},config['token-secret'],{ expiresIn: config['token-expires']});
        let username = 'root_admin'
        let password = 'Admin123';
        let token = String(cryptojs.lib.WordArray.random(20));
        console.log("token : "+token);
        await connection.query('SELECT * FROM users where username = ?  ',[username], async function(err, rows) {
            if (err) {
                console.log("Looged out failed");
            } else {
                const user = rows[0];
                console.log("psdsdsd");
                if(bcrypt.compareSync(password,user.passwordHash)) {
                    await connection.query('SELECT * FROM organizations where id = ?  ',[user.organizationId], async function(err, org_data) {
                        if (err) {
                            console.log("Looged out failed");
                        } else {
                            console.log("sdsd");
                            //console.log(org_data);
                            if(typeof org_data.name!='undefined') {
                                organization = org_data.name;
                            } else {
                                organization = 'VeriCurious';
                            }
                            //console.log(organization);
                            // create a token
                            const token = await jwt.sign({ id: user.id, username: user.username, organizationId: user.organizationId, organization: organization}, config['token-secret'], {
                                expiresIn: config['token-expires'] // expires in 30 minutes
                            }); 
                            console.log("Successfull loggedin");
                            console.log("New generated token : "+token);
                            return token;
                        }
                    });    
                }
            }    
        });

    } catch (error) {
        console.log(error);
    }
}

1 Ответ

2 голосов
/ 07 октября 2019

Когда вы используете await при вызове функции, вы в основном ожидаете разрешения внутри этой функции. Вызванная функция предназначена для возврата этого обещания .

. В вашем коде функция login действительно вызывает connection.query, но нет никакого обещания, которое ожидает запрос кразрешить.

Чтобы заставить await действительно ждать connection.query, вам нужно вернуть Обещание, которое разрешается всякий раз, когда пользователь наконец входит в систему - т.е. у вас есть токен:

const login = async function () {
  try {
    console.log('Login process started');
    const newToken = await jwt.sign({login:'login'},config['token-secret'],{ expiresIn: config['token-expires']});
    let username = 'root_admin'
    let password = 'Admin123';
    let token = String(cryptojs.lib.WordArray.random(20));
    console.log("token : "+token);

    return new Promise(function(resolve, reject){

      connection.query('SELECT * FROM users where username = ?  ',[username], async function(err, rows) { // await won't do anything here,
      // you should only use await with functions that return promises.
        if (err) {
          console.log("Looged out failed");
          throw new Error(err);
        } else {
          const user = rows[0];
          console.log("psdsdsd");
          if(bcrypt.compareSync(password,user.passwordHash)) {
            await connection.query('SELECT * FROM organizations where id = ?  ',[user.organizationId], async function(err, org_data) {
              if (err) {
                console.log("Looged out failed");
                throw new Error(err);
              } else {
                console.log("sdsd");
                //console.log(org_data);
                if(typeof org_data.name!='undefined') {
                  organization = org_data.name;
                } else {
                  organization = 'VeriCurious';
                }
                //console.log(organization);
                // create a token
                const token = await jwt.sign({ id: user.id, username: user.username, organizationId: user.organizationId, organization: organization}, config['token-secret'], {
                  expiresIn: config['token-expires'] // expires in 30 minutes
                }); 
                console.log("Successfull loggedin");
                console.log("New generated token : "+token);
                resolve(token); // this signals the Promise to resolve.
                // return token;
              }
            });
          }
        }    
      });
    });
  } catch (error) {
      console.log(error);
  }
}

Несколько замечаний:

  1. Await предназначен для работы с обещаниями. Асинхронные функции в JavaScript либо принимают обратный вызов, либо возвращают обещание. connection.query принимает обратный вызов, поэтому await здесь бесполезен.
  2. Скорее всего, модуль, который вы используете для общения с базой данных - mongoose? - имеет многообещающий API. Проверьте это, потому что, если вы хотите использовать async / await, лучше работать напрямую с Promises, а не заключать код в новое Promise.

Например, если connection.query вернул aОбещай, ты мог бы сделать что-то вроде:

const login = async function () {
  // skipped a lot of code and logic since this is an example
    const rows = await connection.query('SELECT * FROM users where username = ?  ',[username]);
    const user = rows[0];
    const org_data = await  connection.query('SELECT * FROM organizations where id = ?  ',[user.organizationId]);
    const organization = org_data.name;

    return await jwt.sign({ id: user.id, username: user.username, organizationId: user.organizationId, organization: organization}, config['token-secret'], {
                expiresIn: config['token-expires'] // expires in 30 minutes
  });
}

И обработка ошибок действительно проста.

Когда вы получаете сообщение об ошибке или обратный вызов внутри функции async, и вы возвращаете новое Promise - как в моем примере - я не знаю, лучше ли будет reject или throwОшибка. Я думаю, что оба будут делать то же самое, но я не уверен.
...