2016-04-09 4 views
7

Ich versuche, angular2 zu lernen und erstellte eine Testanwendung mit einem odata Webapi Backend. In der Anwendung habe ich eine Ansicht, die ein Array von Elementen abruft, und ich möchte diese aus meiner Sicht zeigen.Warum muss ich NgZone.run aufrufen, damit meine Ansicht in Angular2 mit breezejs aktualisiert wird?

Zum Abrufen von Daten aus dem Frontend verwende ich die breezejs-Bibliothek, da sie mir in der Vergangenheit viel Zeit erspart hat und ich sie gerne mit einem ODATA-Backend verwende.

Der Aufrufbaum und Anwendungsstruktur sieht wie folgt aus:

Anruf beginnt mit einer Servicefunktion aus der Sicht um die Elemente lostelefonieren holen (beachten Sie, dass ich von jedem Aufruf ein es-6 Versprechen kehre zurück):

this._scrumModuleService.fetchActiveSessions().then((sessions: ScrumSession[]) => { 
    // Here i have to call zone.run else my view wont update. 
    this._zone.run(() => { 
     this.sessions = sessions; 
    }); 
}).catch((error: any) => { 
    debugger; 
}); 

Dann aus der Sicht es in den Dienst gehen, was wiederum das Repository ruft:

public fetchActiveSessions(): Promise<ScrumSession[]> { 
    return this._scrumSessionRepository.fetchActiveSessions(); 
} 

die Reposi Tory holen Funktion:

public fetchActiveSessions(): Promise<ScrumSession[]> { 
    return this._dataContext.fetch(new breeze.EntityQuery().from("ScrumSessions").expand(['creator', 'scrumRoom','productOwner', 'users'])); 
} 

Dann schließlich ruft das Repository die (allgemeine) Datacontext, die die Abfrage mit der Brise EntityManager ausführt:

public fetch(query: breeze.EntityQuery, isRetry: boolean = false): Promise<any> { 

    return new Promise((resolve, reject) => { 
      this.entityManager.executeQuery(query).then((result: breeze.QueryResult): void => { 
      // Data has been fetched, resolve the results 
      resolve(result.results); 
     }); 
    }); 
} 

Nun, wie Sie in der Ansicht sehen, ich habe um die run Funktion von NgZone zu benutzen oder meine Ansicht wird nicht aktualisiert. Ich frage mich, warum ich dies tun muss, da ich erwartet habe, dass angular2 das automatisch für mich sieht. Ich habe durch mehrere similair Fragen gegraben und konnte noch nicht wirklich eine Antwort finden. Ich habe auch das Skript angular2-polyfills wie in einem anderen Thread vorgeschlagen, aber das hat es nicht gelöst.

Was fehlt mir oder was muss ich implementieren, damit meine Ansicht automatisch aktualisiert wird, ohne zone.run aufzurufen?

Antwort

2

Angular-Läufe in einer Zone, in der die meisten asynchronen APIs gepatcht sind. Wenn ein Async-Aufruf abgeschlossen ist, wird die Winkelerkennung geändert.

Irgendwie Brise Code verlässt Angulars Zone und "bricht" Änderung Erkennung. Dies liegt entweder daran, dass Sie Brise außerhalb von Angular initialisieren, oder Brise verwendet eine asynchrone API, die nicht von der Angulars-Zone gepatcht wurde. Daher werden Callbacks außerhalb der Angulars-Zone ausgeführt.

+0

Ich sehe, also bis Brise Unterstützung für angular2 bietet, würden Sie sagen, es ist am besten, nur zone.run für jetzt zu verwenden? –

+0

Ja, benutze 'zone.run()' und stelle sicher, dass es einen Bugreport für breeys gibt, um es zu reparieren. –

6

Breeze läuft jetzt gut mit Angular2. Wir arbeiten an einer großen Anwendung mit der aktuellen Version von Breeze und Angular Beta 8 ohne Probleme.

Die einzige kleine Problemumgehung ist, dass Brise den Angular2-HTTP-Anbieter noch nicht verwendet.Sie können jedoch in dem Standard 'Q' Anbieter Shim so, dass es das ES6 unterstützt verspricht, dass Angular2 mit folgendem Code erwartet:

/** 
 
* Minimum necessary deferred object for breeze Q/ES6 Promise adapter 
 
* Makes ES6 promise look like Q. 
 
*/ 
 
export interface Deferred { 
 
    promise: Promise<any>; 
 
    resolve: (value?: {} | PromiseLike<{}>) => void; 
 
    reject: (reason?: any) => void; 
 
} 
 

 
/** 
 
* Minimum for breeze breeze Q/ES6 Promise adapter 
 
*/ 
 
export const Q = { 
 
    defer(): Deferred { 
 
     let resolve: (value?: {} | PromiseLike<{}>) => void; 
 
     let reject: (reason?: any) => void; 
 
     let promise = new Promise((_resolve, _reject) => { 
 
      resolve = _resolve; 
 
      reject = _reject; 
 
     }) 
 
     return { 
 
      promise: promise, 
 
      resolve(value: any) { resolve(value); }, 
 
      reject(reason: any) { reject(reason); } 
 
     } 
 
    }, 
 

 
    resolve(value?: {} | PromiseLike<{}>) { 
 
     let deferred: Deferred = Q['defer'](); 
 
     deferred.resolve(value); 
 
     return deferred.promise; 
 
    }, 
 

 

 
    reject(reason?: any) { 
 
     let deferred: Deferred = Q['defer'](); 
 
     deferred.reject(reason); 
 
     return deferred.promise; 
 
    } 
 
}

Sie dann diese Datei importieren können

import { Q } from './q';

und dann irgendwo in der Nähe der Spitze Ihrer App

breeze.config.setQ(<breeze.promises.IPromiseService>Q);

An diesem Punkt arbeiten alle Standard-Brisen-Methoden genau so, wie sie es heute tun, und auch Angulars Erkennung von Änderungen sollte keine Probleme haben.

+0

Danke! Sie arbeiten ohne Zone.run jetzt :) perfekt! –

3

Ja, das "Problem" ist, dass Sie eine Art von Versprechens-Bibliothek verwendet haben, von der Zonen nichts wissen (z. B. Q). Glücklicherweise ist die Versprechens-Bibliothek in Breeze steckbar und wir haben ein ES6-Versprechen-Plugin geschrieben, das großartig funktioniert.

Wir haben es noch nicht veröffentlicht (siehe Jay's Antwort oben) noch haben wir das Angular 2 http Plugin noch geschrieben.

Beide sehr einfach, aber wir waren sehr beschäftigt. Sieht so aus, als wäre es an der Zeit.

+0

Danke! Das ist gut zu hören :-) –

+0

Wann werden Sie das Plugin veröffentlichen? – aog

Verwandte Themen