Queremos emitir algumas chamadas $ http no bloco de execução do módulo, idealmente, a execução deve terminar somente depois que $ http e o processamento terminar, antes que a compilação do dom aconteça.
Isso não é tão fácil, mas deve ser investigado.
A maneira como o Jasmine faz isso é definindo um sinalizador, que permitirá que a função seja executada e espere pelo retorno de chamada até que o sinalizador seja definido como true
ou até que um tempo limite seja disparado.
Basicamente, algo assim:
var flag = false;
$http(...).success(flag = true);
$timeout(function () {
flag = true;
// Or add some error handling stuff here
}, 5000);
while (!flag) {};
Não é bonito, mas deve servir. O código acima não foi testado, então você pode precisar modificá-lo um pouco. Está ficando tarde aqui. Esperançosamente, algo para te ajudar até que algo um pouco mais bonito apareça.
+1
Em um segundo, porém, isso leva à incapacidade de desenhar telas de carregamento extravagantes usando diretivas angulares ...
+1
$routeProvider
com resolve
resolve isso? Talvez eu não tenha entendido o problema ...
Isso é mais para suporte de inicialização de módulo assíncrono. Dito isso, não preciso mais disso em meus projetos atuais.
@shahata $routeprovider
faz isso, mas nem todos os casos de uso de run
s de promessa usam rotas. No meu caso de uso, é para um módulo que envolve uma diretiva e não tem nada a ver com rotas.
+1
verifique se a função de execução retorna uma promessa e só prossiga quando for resolvida. já que runBlocks
é uma matriz de funções, não deve ser difícil
+1
+1 embaraçoso por ter sido ignorado
alguma ideia de quando isso vai pousar? tão frustrante ter que mover o material de inicialização para resolver no roteador, principalmente porque às vezes o código de inicialização é agnóstico de url (ou seja, deve ser inicializado para qualquer tipo de URL que o usuário chegue ao seu SPA)
eu não acho que o angular receberá qualquer aprimoramento daqui em diante. estão todos sendo adicionados ao angular 2.0
por quanto tempo o método run
meia-boca permanecerá síncrono? é normal e compreensível que config
não suporte chamadas assíncronas, uma vez que você não tem nenhum provedor que faça $http
chamadas, mas run
sim. veja o tipo de hacks que a falta desse recurso (que deveria estar presente desde o início) causa
https://github.com/philippd/angular-deferred-bootstrap/blob/master/src/deferred-bootstrap.js
é embaraçoso
+1
@btford está examinando como os casos de uso em torno disso podem ser suportados por meio do novo roteador, em vez de blocos de execução internos.
+1
+1
+1
+1
O principal problema que temos é que $q
é criado dentro de um módulo que está sendo carregado quando os runBlocks estão sendo executados. Isso significa que precisaríamos de alguma forma extrair "alguns" dos serviços (ou talvez módulos) e criá-los primeiro e, em seguida, ter uma segunda passagem que carregue o resto dos módulos (e serviços, blocos de execução, etc) após $ q ter foi criado.
@lgalfaso - talvez você pudesse examinar isso um pouco mais como parte do seu $injector
trabalho no final desta semana (ou na próxima)?
Eu sei que é apenas uma solução alternativa, mas normalmente resolvi o problema de ter alguma lógica de inicialização assíncrona usando o roteador ui angular e tendo um estado abstrato raiz em combinação com resolver. O estado abstrato raiz deve ser sempre resolvido primeiro, por isso é um bom lugar para carregar configurações, exibir animações de carregamento, etc.
Isso seria ótimo.
: +1:
Esperando por essa correção. Espero que chegue em 1.4
+1
Eu tenho outro caso de uso: eu preciso iniciar meus endpoints simulados com uma chamada $ http na inicialização (para armazenar alguns dados em cache) ...
+1
+1
apenas tropecei nisso também ...
@petebacondarwin acho que não há problema em continuar carregando todos os outros módulos, mas adie o início da navegação inicial.
alternativamente, o $ routeProvider pode oferecer um parâmetro de função configurável que deve adiar a renderização da rota inicial.
+1
+1
Aqui está uma possível solução alternativa: http://plnkr.co/edit/vi7mDjmD4NpZAoP7MVzr?p=preview
A ideia é que o Angular realmente dê a você a capacidade de criar seu próprio injetor a partir de um conjunto de módulos. Neste caso, adiei a compilação de $rootElement
até que um monte de promessas ( resolves
) fossem resolvidas. Este é um POC e haveria uma série de outros sinos e apitos que seriam necessários para tornar esta produção pronta. Além de qualquer outra coisa, você precisaria detectar os erros nas resoluções, em vez de simplesmente engoli-los.
+1
Este é principalmente um guia para quem quer dar uma chance; Atualmente, o processo de bootstrap faz o seguinte:
$rootElement
$rootElement
Além disso, ao criar o injetor, as etapas são as seguintes:
run
para mais tarderun
Existem alguns pontos-chave:
run
são executados antes de $rootElement
ser compilado$rootElement
$q
resolve promessas durante um ciclo de resumo _somente_Isto é:
run
que retorna uma promessa e a promessa precisa ser resolvida antes do aplicativo iniciar, haverá ciclos de resumo antes da compilação inicial (isso pode interromper os aplicativos existentes)config
é injetada com provedores, não com instânciasSeja qual for a solução, precisa lidar com esses casos
+1
qualquer notícia?
Eu só quero carregar algumas configurações antes de o aplicativo realmente iniciar.
+1
Gostaria de carregar alguns dados assíncronos após o bootstrap quando todas as minhas fábricas estão ativas e antes de compilar.
@dagingaa : Acho que escolheria sua solução como alternativa! obrigado
Atualize para @dagingaa : o loop for congela meus navegadores, não é bom ...
https://jsfiddle.net/tuxmachine/t4d63vnw/
Foi assim que resolvi para uma implementação de token OAuth, que exigia que uma chamada inicial ajax fosse resolvida antes de inicializar o restante do aplicativo.
Não funcionará se você tiver vários blocos de execução assíncrona, no entanto
+1
+1
+1
Já se passaram dois anos desde que o problema foi aberto e ainda não há uma boa solução
@vladmiller Existem soluções, mas talvez você não ache que sejam boas:
$onActivate
no componente de nível superiorColocar trabalho de aplicativo não trivial dentro de blocos .run
torna difícil o teste de unidade de seu código. Portanto, não é algo que queremos encorajar. Movendo isso para a caixa de gelo como algo que provavelmente não implementaremos.
@petebacondarwin, eu discordo de você; todos esperam que o angluar seja simples e intuitivo; em vez disso, você precisa implementar seu próprio módulo de bootstrap assíncrono ou módulo de bootstrap em um lugar diferente. Na minha opinião, isso torna o angular mais complexo.
Você também pode explicar o que quer dizer quando afirma que o código assíncrono em .run
tornará o teste mais difícil?
Peço desculpas pelo meu comentário rude anterior.
Obrigado
@petebacondarwin Não consigo ver como isso torna difícil o teste. se você colocar o código de inicialização em um serviço, você pode apenas assistir / simular / comparar os resultados que você espera da simulação de back-end http, independentemente se ele está sendo executado dentro de um bloco .run
ou não. ter código existindo fora do angular devido a soluções para a falta de execução assíncrona é o que torna quase impossível testar
Como está indo?
Outra abordagem: http://plnkr.co/edit/8XGSNOzzRGvgNSSnXx3M?p=preview
A solução
Como existem soluções alternativas e o suporte a blocos de execução assíncrona aumentaria a complexidade do bootstrap, não acho que implementaremos esse recurso.
Recurso simples, mas muito difícil de implementar. 😕
+1 para este recurso
+1
+1
A solução
+1. :(
+1
+1
+1
+1
Não vamos fazer isso.
+100, todas as soluções alternativas são terríveis.
@Eduardo-Julio - não vamos implementar esse recurso, pois tornaria o bootstrap de aplicativos AngularJS muito mais complexo. Adicionar mais +
s não ajudará.
Comentários muito úteis
Recurso simples, mas muito difícil de implementar. 😕