Eu tenho duas funções JS. Um chama o outro. Dentro da função de chamada, eu gostaria de chamar a outra, aguardar a conclusão da função e continuar. Então, por exemplo / pseudo código:
function firstFunction(){
for(i=0;i<x;i++){
// do something
}
};
function secondFunction(){
firstFunction()
// now wait for firstFunction to finish...
// do something else
};
Eu vim com essa solução, mas não sei se essa é uma maneira inteligente de fazer isso.
var isPaused = false;
function firstFunction(){
isPaused = true;
for(i=0;i<x;i++){
// do something
}
isPaused = false;
};
function secondFunction(){
firstFunction()
function waitForIt(){
if (isPaused) {
setTimeout(function(){waitForIt()},100);
} else {
// go do that thing
};
}
};
Isso é legítimo? Existe uma maneira mais elegante de lidar com isso? Talvez com jQuery?
firstFunction
exatamente isso faz com que seja assíncrono? De qualquer maneira - verificação sobre promessasRespostas:
Uma maneira de lidar com o trabalho assíncrono como esse é usar uma função de retorno de chamada, por exemplo:
Conforme a sugestão de @Janaka Pushpakumara, agora você pode usar as funções de seta para obter a mesma coisa. Por exemplo:
firstFunction(() => console.log('huzzah, I\'m done!'))
Atualização: eu respondi isso há algum tempo e realmente quero atualizá-lo. Embora os retornos de chamada sejam absolutamente bons, na minha experiência, eles tendem a resultar em código mais difícil de ler e manter. Existem situações em que eu ainda as uso, como passar eventos em andamento e coisas do tipo como parâmetros. Esta atualização é apenas para enfatizar alternativas.
Além disso, a pergunta original não specificallty mencionar assíncrona, assim, no caso de alguém está confuso, se a sua função é síncrono, ele vai bloquear quando chamado. Por exemplo:
Se, embora implícita, a função seja assíncrona, a maneira como costumo lidar com todo o meu trabalho assíncrono hoje é com async / waitit. Por exemplo:
Na IMO, async / waitit torna seu código muito mais legível do que usar promessas diretamente (na maioria das vezes). Se você precisar lidar com erros de captura, use-o com try / catch. Leia mais sobre isso aqui: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function .
fonte
Use assíncrono / espera:
em seguida, use aguardar em sua outra função para aguardar o retorno:
fonte
$(function() { await firstFunction(); secondFunction(); });
?await
que só pode ser usado dentro de umasync
método. Portanto, se você colocar seu pai em funcionamento,async
poderá ligar para oasync methods
interior, com ou sem oawait
que deseja.await
umsetTimeout
?Parece que você está perdendo um ponto importante aqui: JavaScript é um ambiente de execução de thread único. Vamos olhar novamente para o seu código, observe que eu adicionei
alert("Here")
:Você não precisa esperar
isPaused
. Quando vocêisPaused
vir o alerta "Aqui",false
jáfirstFunction
estará e retornará. Isso ocorre porque você não pode "ceder" de dentro dofor
loop (// do something
), o loop pode não ser interrompido e terá que ser totalmente concluído primeiro (mais detalhes: manipulação de threads em Javascript e condições de corrida ).Dito isso, você ainda pode fazer com que o código flua
firstFunction
para dentro para ser assíncrono e usar retorno de chamada ou promessa de notificar o chamador. Você teria que desistir dofor
loop e simular com eleif
( JSFiddle ):Em uma nota lateral, o JavaScript 1.7 introduziu a
yield
palavra-chave como parte dos geradores . Isso permitirá "perfurar" orifícios assíncronos no fluxo de código JavaScript síncrono ( mais detalhes e um exemplo ). No entanto, o suporte do navegador para geradores está atualmente limitado ao Firefox e Chrome, AFAIK.fonte
Uma maneira elegante de esperar que uma função seja concluída primeiro é usar o Promises com a função assíncrona / aguardada .
setTimeout
para demonstrar a situação em que as instruções levariam algum tempo para serem executadas.await
a primeira função seja concluída antes de prosseguir com as instruções.Exemplo:
Nota:
Você poderia simplesmente
resolve
oPromise
sem qualquer valor assimresolve()
. No meu exemplo, euresolved
oPromise
com o valory
que eu possa então usar na segunda função.fonte
O único problema com promessas é que o IE não as suporta. O Edge faz isso, mas existem muitos IE 10 e 11 por aí: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise (compatibilidade na parte inferior)
Portanto, o JavaScript é de thread único. Se você não estiver fazendo uma chamada assíncrona, ela se comportará de forma previsível. O thread principal do JavaScript executará uma função completamente antes de executar a próxima, na ordem em que aparecem no código. Garantir a ordem das funções síncronas é trivial - cada função será executada completamente na ordem em que foi chamada.
Pense na função síncrona como uma unidade atômica de trabalho . O principal encadeamento JavaScript o executará totalmente, na ordem em que as instruções aparecerem no código.
Mas, ative a chamada assíncrona, como na seguinte situação:
Isso não faz o que você quer . Ele executa instantaneamente a função 1, a função 2 e a função 3. O carregamento de div pisca e desaparece, enquanto a chamada ajax não está quase completa, apesar de
makeAjaxCall()
ter retornado. A COMPLICAÇÃO é quemakeAjaxCall()
dividiu seu trabalho em partes que são avançadas pouco a pouco a cada rotação do encadeamento principal do JavaScript - está se comportando de maneira assícrona. Mas esse mesmo encadeamento principal, durante uma rodada / execução, executou as partes síncronas de forma rápida e previsível.Então, do jeito que eu lidei com isso : como eu disse, a função é a unidade atômica do trabalho. Combinei o código da função 1 e 2 - coloquei o código da função 1 na função 2, antes da chamada assíncrona. Livrei-me da função 1. Tudo, inclusive a chamada assíncrona, é executada de maneira previsível, em ordem.
ENTÃO, quando a chamada assíncrona for concluída, após várias rotações do encadeamento JavaScript principal, faça com que ela chame a função 3. Isso garante a ordem . Por exemplo, com ajax, o manipulador de eventos onreadystatechange é chamado várias vezes. Quando ele relatar sua conclusão, chame a função final desejada.
Eu concordo que é mais confuso. Eu gosto de ter um código simétrico, de funções fazer uma coisa (ou quase), e não gosto de ter a chamada ajax de forma alguma responsável pela exibição (criando uma dependência no chamador). MAS, com uma chamada assíncrona incorporada em uma função síncrona, é necessário fazer compromissos para garantir a ordem de execução. E eu tenho que codificar para o IE 10, então não há promessas.
Resumo : para chamadas síncronas, garantir a ordem é trivial. Cada função é executada totalmente na ordem em que foi chamada. Para uma função com uma chamada assíncrona, a única maneira de garantir a ordem é monitorar quando a chamada assíncrona for concluída e chamar a terceira função quando esse estado for detectado.
Para uma discussão sobre threads JavaScript, consulte: https://medium.com/@francesco_rizzi/javascript-main-thread-dissected-43c85fce7e23 e https://developer.mozilla.org/en-US/docs/Web/JavaScript/ EventLoop
Além disso, outra pergunta semelhante e bem cotada sobre esse assunto: como devo chamar 3 funções para executá-las uma após a outra?
fonte
Foi assim que surgiu, pois preciso executar várias operações em uma cadeia.
fonte
Sua diversão principal chamará firstFun e, depois disso, sua próxima diversão chamará.
fonte