Architettura angolare

1

Ho sviluppato alcune applicazioni prototipo in Angular, con vari backend, tra cui firebase e php / mysql. Sono abbastanza sicuro di non utilizzare un buon modello organizzativo per lo sviluppo a causa di un paio di klug che devo usare nel codice per evitare l'eccezione "iterazione massima raggiunta".

Ho un modello con una ng-repeat, come questa:

<ion-item data-ng-repeat="outcome in Outcomes.getAll()">...</ion-item>

È supportato da un servizio come questo:

'usa strict';

angular.module ('app.outcomes', ['app.utility']). servizio ('Risultati', funzione ($ http, Utility) {     var svc = questo;     svc.outcomes = false;

/**
 * Initializes the outcomes array if it has not yet been initialized.
 *
 * @returns {Array}
 */
svc.initialize = function () {
    if (svc.outcomes === false) {
        // If this is not set to something immediately, repeated calls to 
        // digest occur during http call and digest overloads.
        svc.outcomes = true; 
        $http.get('/api/outcome/all').
            success(function (data, status, headers, config) {
                        svc.outcomes = data.result; // set data to real array value
                    }).
            error(function (data, status, headers, config) {
                  });
    }
};

/**
 * Called in ng-repeat so that it makes sure the data is initialized.  
 * An ng-init call does not work.
 * @returns {Array}
 */
svc.getAll = function () {
    svc.initialize();  // called constantly from ng-repeat, while array actually set
    return svc.outcomes;
};});

Il controller è un one-liner che imposta la variabile $ scope.Outcomes sul servizio.

Questa strategia funziona, perché il ciclo digest verifica la condizione. Quello che sembra klugy per me è che ho bisogno di impostare la matrice dei risultati su un valore inutilizzato mentre aspetto che la chiamata ajax torni. Altrimenti viene chiamato il ciclo del digest e tenta di continuare a farlo per quanto a lungo dura la chiamata per tornare dal server.

Un altro problema correlato che ho è che se imposto l'array svc.outcomes più tardi, a volte otterrò lo stesso errore su troppe iterazioni di digest.

Le domande che ho sono:

1) C'è un modo migliore per organizzare il codice? Devo poter accedere ai dati del server su più ambiti.

2) C'è un modo per garantire che l'array di dati venga inizializzato senza dover chiamare il metodo getAll () nel ciclo ng-repeat? Una chiamata ng-init non compila i dati, quindi non posso semplicemente riferire Outcomes.outcomes nel modello.

Ciò che è strano per me è che penso che la cosa delle "iterazioni massime" sia appena iniziata con l'uso di un aggiornamento minore (da 1.3.3 a 1.3.6) ad angolare. Potrebbe essere la mia immaginazione. Qualsiasi suggerimento architettonico sarebbe apprezzato.

    
posta davidquinnjacobs 24.03.2015 - 01:17
fonte

1 risposta

2

TLDR;

1) Sì, c'è un modo migliore.
2) Sì, non dovresti attivare una richiesta HTTP in una ng-repeat

Risposta completa

Devi capire come funziona ng-repeat. Ogni volta che viene eseguito il ciclo di digest, controlli angolari per vedere se l'array nella ng-repeat è cambiato. E quando lavori con l'angolatura, ti consiglio di pensare al ciclo di digest come qualcosa che funziona TUTTO IL TEMPO. Tutto ciò che fai in angolare genera un ciclo di digestione. Cliccato da qualche parte? Il ciclo di digest è appena finito. Modificato un valore in un input da qualche parte? Il ciclo di digest è appena finito. Passava sopra qualcosa con un suggerimento di bootstrap angolare (perché pensavi che quelle cose fossero molto più belle dei titoli)? Il ciclo di digest è appena finito. Respirato troppo strong? Il ciclo di digest è appena stato eseguito.

Ecco perché sentirai spesso dire alle persone che non dovresti ripetere le funzioni. Non perché sia una regola dura e veloce, ma perché in generale, non si vuole forzare l'angolare a dover eseguire quella funzione ogni volta che succede qualcosa sulla pagina solo per vedere se il valore restituito è cambiato. Fai di te un favore e ng-repeat su un array, non una funzione che restituisce un array.

Questo mi porta al prossimo punto. Se si esegue ng-repeat su una funzione, assicurarsi che la funzione restituisca sempre lo stesso array. Non intendo un array con gli stessi elementi, o un array che sembra lo stesso, ma lo stesso oggetto javascript. Se non lo fai, ti ritroverai con un errore di diger mass massimo raggiunto. Questo perché anche se il contenuto dell'array è lo stesso, gli oggetti reali sono diversi.

Quindi come dovresti farlo?

Nel controller, chiama il metodo di inizializzazione sul servizio. Questo popolerà la matrice outcomes . Nella tua ng-repeat, esegui l'iterazione direttamente sull'array outcomes . Per fare ciò, devi esporre due cose dal tuo servizio: la funzione initialize (lo stai già facendo) e l'array outcomes compilato nel metodo success della tua chiamata $http.get . Puoi eliminare la funzione getAll .

Nota finale

Suppongo che tu debba davvero eseguire la richiesta HTTP solo una volta. Se devi eseguire sempre la richiesta HTTP per riflettere le modifiche sul server, devi iniziare a pensare ad altre soluzioni a questo problema (websocket, ecc.). Non puoi eseguire una richiesta HTTP all'interno del ciclo di digest e aspettarti che la tua app risponda normalmente.

    
risposta data 06.05.2015 - 22:31
fonte

Leggi altre domande sui tag