await does not await execution of the President

Asked

Viewed 393 times

5

I thought I understood how asynchronous function works with await. In my understanding the await was waiting for the resolve of Promise to continue to the following.

To test this operation, I created two functions that return a promise and included a timer (simulating database access). I noticed that the code was executed asynchronously, ignoring the await.

function getSenha() {
    return new Promise(function(resolve, reject) {
                setTimeout( function() {
                    console.log( 'Executa uma vez após 9 segundos.' );
                  }, 9000 );                    
                resolve("RET_SENHA");
    });
};

function getMensagem() {
    return new Promise((resolve, reject) =>{
        setTimeout( function() {
            console.log( 'Executa uma vez após 1 segundo.' );
            }, 1000 );          
            resolve("RET_MSG");
    });
}


async function montaMensagem() {
    const senha = await getSenha();
    const msg = await getMensagem();

    console.log('Senha: ', senha);
    console.log('Mensagem: ', msg);
}
montaMensagem();

Follow the result:

Senha:  RET_SENHA
Mensagem:  RET_MSG
Executa uma vez após 1 segundo.
Executa uma vez após 9 segundos.

The right thing wouldn’t be:

Executa uma vez após 9 segundos.
Executa uma vez após 1 segundo.
Senha:  RET_SENHA
Mensagem:  RET_MSG

With the consultation at the Bank:

getSenha() {
        return new Promise((resolve, reject)=> {
            let connection = AtendimentoDB.connect();
            let sql = "select * from senha";

            connection.query(sql, function (error, results, fields) {
                if (error) {
                    reject(error);
                } else {
                    resolve(results);
                }
            });
            connection.end();
        });
    };

getMensagem() {
        return new Promise((resolve, reject) =>{
            let connection = AtendimentoDB.connect();
            let sql = "SELECT mensagem FROM configuracao;";
            connection.query(sql, function (error, results, fields) {
                if (error) {
                    reject(error);
                } else {
                    resolve(results);
                }
            });
            connection.end();

        });
};

async function montaMensagem() {
    const senha = await getSenha();
    const msg = await getMensagem();

    console.log('Senha: ', senha);
    console.log('Mensagem: ', msg);
}
  • try to put async in getMensage() and getNo()

  • @Otaviocapel, thanks for the tip, but it didn’t work. From what I understand, only the function that will use the await needs to be async, I’m sure?

  • 1

    Don’t you need to put the solutions within the timeout? It actually runs the Function of the timeout after a certain period, but at how much this, it keeps running the code (in case it solves it)

  • I did the test here by placing the resolve within the timeout and in fact there was the expected result, would be this?

  • 1

    It would not be right to put the "resolve("RET_SENHA")" within the timeout Function?

  • @Leonardobuta, you’re right. The correct thing would be to include within the setTimeout. Thanks for the return.

Show 1 more comment

1 answer

7


TL;DR: The problem is not in asynchronous function and/or in await. As mentioned by @Leonardo Buta in the comments of the question, problem lies in its implementation of the examples getSenha and getMessage, since the resolve() should have been called inside the setTimeout.


Assuming that both getSenha how much getMessage do exactly the same thing, I will illustrate the reason of the situation using the first function presented:

function getSenha() {
  return new Promise(function(resolve, reject) {
    setTimeout( function() {
        console.log( 'Executa uma vez após 9 segundo.' );
    }, 9000 );                    
    resolve("RET_SENHA");
  });
};

In it, we can affirm that the resolve() is out of the setTimeout, which causes the promise to be resolved immediately after your call, causing only the console.log wait for 9 seconds. This immediate resolution of Promise gives us the impression that the await does not work (since the promise is resolved instantly and we do not have this perception). In fact, the await stopped the execution of the function by an extremely small number of time.


The example below shows the difference between putting the resolve inside and outside the setTimeout:

function withinSetTimeout() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Console.log: [1] (Dentro do setTimeout)')

      // Note que o `resolve` está dentro do `setTimeout`. Isso faz com que
      // a Promise só seja resolvida quando o tempo de espera (2s) acabar.
      resolve('[1] De dentro do setTimeout!')
    }, 2000)
  })
}

function outsideSetTimeout() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Console.log: [2] (Dentro do setTimeout)')
    }, 2000)

    // Por estar fora do `setTimeout`, a Promise será resolvida
    // imediatamente (não haverá nenhum aguardo).
    resolve('[2] De fora do setTimeout!')
  })
}

async function ex1() {
  const result1 = await withinSetTimeout()
  console.log('[1] Resultado:', result1)
}

async function ex2() {
  const result2 = await outsideSetTimeout()
  console.log('[2] Resultado:', result2)
}

ex1()
ex2()


And to clarify: the await for execution within the asynchronous function until the Promise that it is waiting to be resolved or rejected. This statement may be confirmed by means of documentation relating to await on MDN.

See the demo below:

// A função abaixo cria uma função que pausa o código dentro de uma função
// assíncrona por um dado tempo.
function wait(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

// Demonstração da pausa causada pelo `await`:
async function main() {
  console.log('[1] Serei executado imediatamente!')
  await wait(800)
  console.log('[2] Fui executado após 800ms após o primeiro!')
  await wait(900)
  console.log('[3] Fui executado 900ms após o segundo!')
  await wait(1000)
  console.log('[4] Fui executado 1s após o terceiro!')
}

main()


Responses to comments

In response to the question’s comments:

From what I understand, only the function that will use the await needs to be async, I’m sure?

Yes! Only the function that will use the await needs to be marked as asynchronous. In other cases, this marking will be unnecessary, although it has no negative impact on the code.

In the real situation will be a query to the database, would not be able to use a timeout.

In that case, the await will await the query to the database, waiting for the query time. At that time, the execution of the asynchronous function will be paused. The setTimeout in its example was this delay of the consultation, and therefore the resolve should have been placed inside the setTimeout, representing the moment when the data will be resolved.

If the consultation to the bank will be expected, because the same did not happen with the timeout?

The consultation of the bank will be awaited because the Promise will only be resolved when the query properly performed and return the data, which will be resolved by the promise. It’s like something like this:

  1. You call the method db.query;
  2. He performs the query in your database;
  3. Once the data is resolved, the promise is resolved.
  4. In case of mistakes, the promise is rejected.

You didn’t do this simulation correctly, because as I explained at the very beginning of the answer, you would have to have put the resolve() within the setTimeout (what would simulate the waiting time of the query). What did you call the resolve outside the setTimeout, the promise was resolved immediately.

  • Luiz, thank you for the excellent answer, but I still had a doubt. If the bank consultation will be expected, why didn’t the same happen with the timeout? We can talk tomorrow ?

  • I edited the question. See if it’s clearer.

  • Luiz, come on. My doubt should be about something very basic, I’m starting. I understood your placement, but my only question is: both the timeout and the query are two processes, because the query interrupts the processing and the timeout passed directly. I’ll include a Jsfiddle to detail my question.

  • Luiz, in my understanding the fact of using await in the call of the function, this would cause the function to be executed synchronously, that is, line by line awaiting the completion of each line. In the example of setTimeout, I thought I should wait the seconds, display the message on the console and only then return the resolve. Why wasn’t it executed that way? That’s my question. Thanks for the force.

  • Luiz, with your help I was able to clarify my doubt. Now just practicing so that the concept is assimilated. Thank you.

  • Luiz, I changed my answer to Leonardobuta, he was really correct.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.