Esperar por uma função para terminar em JavaScript
-
Sync
eAsync
em JavaScript -
Utilize
callback
para esperar por uma função para terminar em JavaScript -
Utilize
promises
para Esperar por uma Função para Terminar em JavaScript -
Utilize
async/await
para esperar que uma função termine antes de continuar a execução
Este tutorial irá introduzir JavaScript Callbacks
, Promises
, e Async/await
e mostrar-lhe-á como esperar que uma função async termine antes de continuar a execução.
Para compreender o que são Promises
e Async/await
, precisamos primeiro de compreender o que são as funções Sync
e Async
em JavaScript.
Sync
e Async
em JavaScript
A programação síncrona executa um comando de cada vez. Quando chamamos uma função que executa uma acção de longa duração, ela pára o programa até que este termine.
O JavaScript é tradicionalmente de rosca única, mesmo com múltiplos núcleos. Podemos conseguir que execute tarefas apenas num único string chamado string principal.
Este comportamento sincronizado é um factor limitativo nos multi-tarefas, mas ajuda o utilizador a escrever códigos sem se preocupar com problemas de simultaneidade.
Enquanto na programação assíncrona, a acção de longo prazo será executada noutro string que não o string principal, pelo que a execução principal não é bloqueada. Quando essa função de longa duração termina, o programa principal é informado e tem acesso aos resultados.
A maioria das primitivas E/S em JavaScript não estão bloqueadas. Pedidos de rede, operações de sistemas de ficheiros são todas operações de não-bloqueio. Estar bloqueado é a excepção em JavaScript.
Uma vez que o JavaScript se baseia em técnicas de programação assíncrona, existem múltiplas abordagens tais como callbacks
, promises
e async/await
, permitindo-lhe colocar as suas execuções de funções em sequência. Para que um bloco de código ou uma função não seja executado antes de outra função específica terminar.
A figura acima mostra a clara variação entre a execução assíncrona e síncrona de duas funções.
Utilize callback
para esperar por uma função para terminar em JavaScript
Se tivermos declarações síncronas, então a execução dessas declarações uma após a outra é directa.
function one() {
console.log('I am function One');
}
function Two() {
console.log('I am function Two');
}
one();
Two();
Resultado:
I am function One
I am function Two
Suponhamos que queremos executar duas funções, functionOne()
e functionTwo()
de tal forma que functionOne()
devam ser executadas após a execução de algumas instruções assíncronas dentro de functionTwo()
.
function functionOne(_callback) {
// do some asynchronus work
_callback();
}
function functionTwo() {
// do some asynchronus work
functionOne(() => {
console.log('I am a callback');
});
}
functionTwo();
Ao executar o código acima, a última coisa impressa na consola é I am a callback
. O famoso exemplo callback
é a função setTimeout
com uma função de manipulação a executar depois de expirado o tempo.
function testCallBack() {
console.log('log before use setTimeout function');
setTimeout(() => {
console.log('inside timeout');
}, 5000);
console.log('log after use setTimeout function');
}
testCallBack();
Resultado:
log before use setTimeout function
log after use setTimeout function
inside timeout
Utilize promises
para Esperar por uma Função para Terminar em JavaScript
Um promises
é um objecto que representa o eventual cumprimento ou falha de uma operação assíncrona. Anexamos a chamada de retorno do cumprimento ao promises
com uma ou mais declarações then
, e quando se pode chamar o manipulador do erro na catch
.
doFirstThing()
.then(result => doSecondThing(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log('The final result thing' + finalResult);
})
.catch(failureCallbackfunction);
}
Encadear as declarações de then
e catch
como o exemplo acima é uma das vantagens das promessas. Prometemos doSecondThing(result)
uma vez que o doFirstThing()
seja cumprido. Os argumentos para o then
são opcionais, mas necessários se tiver de devolver um resultado.
No caso de haver um erro, o navegador irá olhar para o fim da string para o catch
e executá-lo. É muito semelhante à famosa try-catch
.
O exemplo seguinte irá ajudar-nos a compreender as strings de promises
e mostrar-nos como podemos esperar que uma função com comportamento assíncrono termine a execução antes de podermos continuar a execução.
var resolvedFlag = true;
let mypromise = function functionOne(testInput) {
console.log('Entered function');
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Inside the promise');
if (resolvedFlag == true) {
resolve('Resolved');
} else {
reject('Rejected')
}
}, 2000);
});
};
mypromise()
.then((res) => {console.log(`The function recieved with value ${res}`)})
.catch((error) => {
console.log(`Handling error as we received ${error}`);
});
Resultado:
Entered function
Inside the promise
The function received with value Resolved
Criar uma promessa pode ser tão fácil como devolver um novo Promessa()
. O Promise()
construtor recebe uma função como argumento, que deve ter dois parâmetros - resolver
e rejeitar
.
No caso do nosso evento ser cumprido, e precisamos de devolver o resultado, utilizamos a função resolve()
quando somos bem sucedidos no que estávamos a fazer. Mas se um erro acontecer e precisar de ser tratado, utilizamos a função reject()
para enviar o erro para a função catch
.
Definimos a bandeira resolvedFlag = true
para simular a manipulação do erro no catch
. Se resolvedFlag
estiver definida para ser false
, a função reject()
é chamada, e o erro é tratado no bloco catch
.
Resultado:
Entered function
Inside the promise
Handling error as we received Rejected
Utilize async/await
para esperar que uma função termine antes de continuar a execução
Outra forma de esperar que uma função seja executada antes de continuar a execução no ambiente assíncrono em JavaScript é utilizar async/wait
.
A função async
é a função que é declarada pela palavra-chave async
, enquanto apenas a palavra-chave await
é permitida dentro da função async
e utilizada para suspender o progresso dentro da função assíncrona até que a operação assíncrona baseada na promessa seja cumprida ou rejeitada.
As palavras-chave async
e await
permitem um comportamento assíncrono, baseado na promessa, num estilo mais limpo.
Vamos compreender como funciona o async/await
. A função pela qual estamos à espera deve devolver uma instância da classe Promise para esperar que ela seja executada utilizando a palavra-chave await antes de a chamar. Como mencionado acima, a função que contém a declaração async/await
deve ser declarada com a declaração async
.
O exemplo seguinte mostra como esperar que essa função baseada na promessa termine antes de continuar a execução.
function testAsync() {
return new Promise((resolve, reject) => {
// here our function should be implemented
setTimeout(() => {
console.log('Hello from inside the testAsync function');
resolve();
;
}, 5000);
});
}
async function callerFun() {
console.log('Caller');
await testAsync();
console.log('After waiting');
}
callerFun();
Resultado:
Caller
Hello from inside the testAsync function
After waiting