Estou tentando entender melhor as nuances do uso do serviço $ timeout em Angular como uma espécie de método “safe $ apply”. Basicamente, em cenários em que um trecho de código poderia ser executado em resposta a um evento Angular ou a um evento não angular, como jQuery ou algum evento DOM padrão.
Pelo que entendi as coisas:
Olhando para código-fonte Angular, parece que $ timeout faz uma chamada para $ rootScope. $ Apply ().
Obrigado por qualquer insight.
Olhando para código-fonte Angular, parece que $ timeout faz uma chamada para $ rootScope. $ Apply ().
- Por que o $ timeout () também gera um erro se um ciclo de digitação já está em andamento?
$timeout
faz uso de um $browser
serviço angular não documentado. Especificamente, ele usa $browser.defer()
que adia a execução de sua function de forma assíncrona via window.setTimeout(fn, delay)
, que sempre será executado fora do ciclo de vida Angular. Apenas uma vez window.setTimeout
disparou sua function, $timeout
chamará $rootScope.$apply()
.
- É a melhor prática usar o $ scope. $ Apply () quando você tem certeza de que um resumo não estará em progresso e $ timeout () quando precisar que ele seja seguro de qualquer forma?
Eu diria que sim. Outro caso de uso é que às vezes você precisa acessar uma variável $ scope que você sabe que só será inicializada após o resumo. Exemplo simples seria se você quiser definir o estado de um formulário para sujo dentro do construtor do controlador (por qualquer motivo). Sem $ timeout, o FormController
não foi inicializado e publicado no $ scope, portanto, $scope.yourform.setDirty()
dentro de $ timeout garante que o FormController
tenha sido inicializado. Claro que você pode fazer tudo isso com uma diretiva sem $ timeout, apenas dando outro exemplo de caso de uso.
- É $ timeout () realmente aceitável “seguro aplicar”, ou existem dicas?
Deve ser sempre seguro, mas seu método deve sempre apontar para $ apply () na minha opinião. O aplicativo Angular atual em que estou trabalhando é bastante grande e só tivemos que confiar em $ timeout uma vez, em vez de $ apply ().
Se usarmos $ apply fortemente no aplicativo, poderemos obter o erro: $ digest já em andamento. Isso acontece porque um ciclo $ digest pode ser executado por vez. Podemos resolvê-lo por $ timeout ou por $ evalAsync.
O $ timeout não gera erro como “$ digest já em progresso” porque $ timeout diz ao Angular que após o ciclo atual, há um timeout aguardando e assim garante que não haverá colisões entre ciclos de digitação e, portanto, saída de $ O tempo limite será executado em um novo ciclo $ digest.
Eu tentei explicá-los em: Comparação de aplicar, timeout, digest e evalAsync .
Talvez isso te ajude.
Até onde eu entendi, $timeout
é um wrapper em torno de setTimeout
que implicitamente chama $scope.$apply
, o que significa que ele é executado fora do ciclo de vida angular, mas kickstarts o próprio ciclo de vida angular. A única “pegadinha” em que posso pensar é que, se você está esperando que seu resultado esteja disponível neste $digest
, você precisa encontrar outra maneira de “aplicar com segurança” (que, AFAIK, só está disponível via $scope.$$phase
).