2016-08-31 16 views
5

Zauważyłem dziwne zachowanie z moimi komponentami za pomocą Angular 2. Moje widoki zajmują kilka sekund, aby zostać zaktualizowane, gdy mój składnik zmieni model jako moich dostawców. Nawet jeśli dane z API to pojedyncze dane.Opóźnienie Angular2 do aktualizacji

Na przykład:

mam jak mój Provider model o nazwie UserModel Wewnątrz mój komponent uzyskać dane z API, a następnie aktualizować ten model, który jest również wewnątrz mojego widoku. Po otrzymaniu odpowiedzi od serwera aktualizowanie mojego widoku trwa kilka sekund, a czasami nie jest aktualizowana, zaraz po kliknięciu dowolnego kontrolera tekstu na tej samej stronie, a następnie mój widok jest aktualizowany po ustawieniu dowolnego tekstu.

Czy ktoś już to widział? Co mogłem robić źle?

Komponent Karta

public createCard(model:CardModel):Promise<any>{ 
    var context = this; 
    return new Promise((resolve, reject) => { 
    this.stripe.createToken(model) 
     .then(function(token){ 
      model.token = token; 
      context.saveCard("./card", model, true) 
        .then(data => resolve(data)) 
        .catch(error => reject(error)); 
     }) 
     .catch(error => reject(error)); 
}); 

Stripe usługi

public createToken(model:CardModel):Promise<any>{ 
    //I get callback and convert return it as promise 
    return new Promise((resolve, reject) => { 
      //this function is the one from stripe.js, it is not promise 
      this.stripe.card.createToken(model, function(status, response){ 
      if(status == 200){ 
       resolve(response.id); 
      }else{ 
       reject(response.error.message); 
      } 
     }); 
    }); 
} 

Jeśli zauważysz funkcję createToken powraca jako zwrotnego, ponieważ jest to funkcja Strip.js, a następnie przekonwertować go do Obiecaj go zwrócić utworzyć CreateCard. Ale gdy wszystkie funkcje zostaną zakończone, moja strefa nie zostanie zmieniona. Jeśli usuniemy this.stripe.card.createToken i zwrócę proste rozstrzygnięcie() przy użyciu limitu czasu, to działa poprawnie. Tak więc uważam, że problem polega na tym, że funkcja asynchroniczna zwraca komunikat zwrotny wewnątrz obietnicy. Ale nie mam pojęcia, jak sobie z tym poradzić.

+0

Jest to zwykle, gdy jakiś kod, który działa poza Angulars strefie aktualizuje dane Niektóre API z wywołań zwrotnych, które nie są. łatany przez strefę Angulars może to spowodować.W tym przypadku Angular nie wie, że musi uruchomić detekcję zmian.Muszę zobaczyć jakiś kod –

+0

Zaktualizowałem pytanie, dodając trochę kodu – Angular2

+0

'Obietnica' może zależeć od niektórych polyfill kolejność ładowania Jeśli użyjesz Observable, to zdecydowanie powinno zadziałać, poza tym nic nie ma podejrzliwy. –

Odpowiedz

0

Wygląda na to, że używasz biblioteki innej firmy, która nie działa dobrze z Angular 2. Miałem ten sam problem z StripeJS. Problem związany jest z Angular's Zone.js i Lifecycle - jest to bardzo podobne do tego błędnego wydania cyklu w Angular 1. Angular ma szczegółową dokumentację rozwiązania tutaj: https://angular.io/api/core/ChangeDetectorRef#example-live-demo

Aby to rozwiązać, musisz wdrożyć własną pętlę cyklu życia i dodaj bibliotekę osób trzecich do wykrywania zmian. Moja implementacja dla StripeJS (również pamiętać, aby zniszczyć setInterval z clearInterval:

import { 
 
    Component, 
 
    Input, 
 
    Output, 
 
    EventEmitter, 
 
    AfterContentInit, 
 
    ChangeDetectorRef, 
 
    ChangeDetectionStrategy, 
 
    ViewContainerRef, 
 
    OnDestroy 
 
} from '@angular/core'; 
 

 
@Component({ 
 
    selector: 'v-payment-form', // <payment-form></payment-form> 
 
    changeDetection: ChangeDetectionStrategy.OnPush, 
 
    templateUrl: './payment-form.component.html' 
 
}) 
 
export class PaymentFormComponent implements AfterContentInit, OnDestroy { 
 
    checker: any; 
 
    constructor(private changeDetectorRef: ChangeDetectorRef) { 
 
    this.checker = setInterval(() => { 
 
     // the following is required, otherwise the view will not be updated 
 
     this.changeDetectorRef.markForCheck(); 
 
    }, 75); 
 
    } 
 
    addPaymentMethod() { 
 
    Stripe.card.createToken(cardDetails) 
 
    this.changeDetectorRef.detectChanges() 
 
    } 
 
    ngAfterContentInit() { 
 
    // ..load stripe js here - I use scriptjs 
 
    } 
 
    ngOnDestroy(): void { 
 
    clearInterval(this.checker) 
 
    } 
 
}

Powiązane problemy