Ember.js: [Glimmer 2] "Backtracking re-render" ist jetzt eine Behauptung

Erstellt am 29. Juli 2016  ·  63Kommentare  ·  Quelle: emberjs/ember.js

Backtracking Re-Rendering bezieht sich auf ein Szenario, in dem Sie mitten im Rendering-Prozess etwas geändert haben, das bereits gerendert wurde.

Zum Beispiel:

{{foo}} {{foo-bar parent=this}}
// app/components/foo-bar.js

export default Ember.Component.extend({
  init() {
    this._super(...arguments);
    this.get('parent').set('foo', 'bar');
  }  
});

Wie Sie sehen, haben wir zu dem Zeitpunkt, zu dem die foo-bar Komponente instanziiert und gerendert wird, bereits den Wert foo aus dem übergeordneten Kontext verwendet, um die {{foo}} Schleife zu füllen. In seinem Konstruktor wurde jedoch versucht, denselben Wert zu ändern. "Rückverfolgung".

Dies ist ein ziemlich extremes Beispiel, aber es veranschaulicht das Problem. Außer init , didInitAttrs , didReceiveAttrs , willInsertElement und willRender geschieht auch synchron während des Rendervorgangs. Darüber hinaus ist Backtracking häufig ein Problem, das sich aus dem Verhalten von bidirektionalen gebundenen Eigenschaften ergibt.

Dieses Verhalten war schon immer unzuverlässig, wurde aber teilweise mit einer Einstellung unterstützt (seit Ember 1.13):

You modified ApplicationController.foo twice in a single render. This was unreliable in Ember 1.x and will be removed in Ember 3.0

Seit 1.13 unterstützt Ember dies, indem es sofort ein zweites Re-Rendering durchführt, wenn ein Backtracking erkannt wurde (und dann wiederholt wird, bis sich das System stabilisiert hat). Diese Strategie selbst könnte eine Quelle von Leistungsproblemen sein. Im Extremfall kann dies zu einer Endlosschleife führen.

In Glimmer 2 ist zwar das zusätzliche Re-Rendering relativ günstig, die zusätzliche Buchhaltung zum Erkennen eines Backtrackings set jedoch nicht. Einer der Vorteile des Glimmer 2-Systems besteht darin, dass es nicht eifrig Beobachter einrichten muss, um Änderungen zu verfolgen. Darüber hinaus ermöglichen bestimmte Optimierungen in Glimmer 2 dem System, das Durchqueren von Teilbäumen zu überspringen, wenn es weiß, dass sich darin nichts geändert hat.

Zusammengenommen bedeuten diese Faktoren, dass wir diese rücklaufenden set s (oder ob etwas "bereits gerendert" wurde oder nicht) nicht ohne weiteres erkennen können, ohne eine große Menge zusätzlicher Buchhaltung zu betreiben und diese Optimierungen absichtlich zu umgehen.

Wir haben bereits den Code geschrieben, um dies zu unterstützen, aber aufgrund der ohnehin unzuverlässigen Natur der Funktion und der (sehr erheblichen) Buchhaltungskosten zögern wir, sie automatisch für alle zu aktivieren, ohne zu wissen, ob sie noch benötigt wird.

Als Kompromiss führen wir die Erkennung derzeit nur im Entwicklungsmodus durch und haben die Deprecation-Meldung in eine Entwicklungsmodus-Assertion (harter Fehler) umgewandelt. Im Produktionsmodus wird der Erkennungscode entfernt und die Rückverfolgung funktioniert nicht.

Wir haben die Möglichkeit beibehalten, dieses Feature (ohne die Assertion) in der Codebasis hinter einem zweiten Feature-Flag zu unterstützen. Der Code wird kontinuierlich auf CI getestet, ist jedoch standardmäßig deaktiviert, bis wir genügend Nutzungsinformationen haben, um die nächsten Schritte zu bestimmen.

Wenn Sie glauben, dass Ihr Nutzungsverhalten davon betroffen ist, geben Sie bitte unten so viele Details wie möglich zu Ihrem Szenario an. Es ist sehr gut möglich, dass wir Alternativen und/oder gezielte Lösungen verwenden können, die keine umfassende Änderung des Motors erfordern. Daher wäre es hilfreich, wenn Sie Hintergrundinformationen und Kontext zu Ihrer Verwendung bereitstellen, anstatt uns nur kleine Codeschnipsel aus Ihrer Codebasis zu zeigen.

Ember 2.10 Inactive

Hilfreichster Kommentar

Dies wurde im Blog-Beitrag 2.10 nicht erwähnt und überraschte mich, da die Veraltungswarnung zuvor besagte, dass es, wie oben erwähnt, bis 3.0 unterstützt wird.

Alle 63 Kommentare

Zu Ihrer Information, wir hatten einige dieser Warnungen in unserer App. Insbesondere haben wir einige Eigenschaften eines Dienstes in init einer Komponente aktualisiert, was dazu führen würde, dass etwas anderes auf der Seite anders gerendert wird.

Es ist sehr einfach, diese Warnung zu beheben, indem Sie die Eigenschaftsänderung in der nächsten Laufschleife planen. Ich habe ~ eine Stunde gebraucht, um alle Warnungen in unserer (ziemlich großen) App aufzuspüren und zu beheben. Obwohl dies technisch gesehen eine bahnbrechende Änderung ist, stimme ich Ihrer Einschätzung zu, auch wenn sie mir zusätzliche Arbeit verursacht hat.

@fivetanley die Fehlermeldung hier zu verbessern klingt gut. Ich weiß, dass @krisselden und @stefanpenner einen Workflow haben, um diese Probleme aufzuspüren, vielleicht können sie Ihnen dabei helfen.

@joukevandermaas run.next() ist keine großartige Lösung für diesen Fehler, obwohl ich verstehe, wenn Sie mit diesen Fehlern überfordert sind, warum Sie dorthin gehen würden. Am besten versuchen Sie zu verstehen, warum der Rückfluss von Daten bereits gerenderte Dinge ungültig macht.

Wenn Sie Eigenschaften für einen Dienst festlegen, der auf eine beliebige Komponente injiziert werden könnte, erhöht sich wahrscheinlich die Wahrscheinlichkeit, dass dieser Satz etwas ungültig macht, das bereits gerendert wurde. Im Allgemeinen sollte das Muster sein, dass set() nur für den internen Zustand während Rendering-Hooks verwendet wird, nicht an Eingaben oder Dienste gebunden ist, und oder set() für ein Ereignis verwendet wird, der Eingabezustand sollte durch die Zeit, die das Zeug rendert, festgelegt werden.

@joukevandermaas run.next() ist keine großartige Lösung für diesen Fehler.

Dies führt zu Leistungsproblemen, da glimmer2 in diesem Fall mitteilt, dass "Doppelarbeit stattfindet, Sie möchten dies wirklich nicht, wenn Sie eine leistungsstarke App wünschen". Wo zuvor würde Glut dies absorbieren, aber zu einer starken Leistungseinbuße führen.

Wir haben hier noch weitere Aufgaben zum Wissensaustausch... Letztendlich glauben wir, dass dies ein gesunder Weg nach vorne für Apps ist. Aber wir müssen sicherstellen, dass jeder die Werkzeuge + das Wissen hat, um davon zu profitieren :)

Als Person, die das Geschehen von Ember relativ genau verfolgt (Twitter, hier auf Github, Mailinglisten usw.), hat sich dieses Problem auf mich eingeschlichen, daher würde ich vermuten, dass dies andere überraschen könnte, wenn es als Teil von Ember 2.10 landet, insbesondere weil die damit verbundene Veraltungswarnung gibt ausdrücklich an, dass das Verhalten bis 3.0 unterstützt wird. Ich glaube nicht, dass ich irgendwo gesehen habe, dass dieses Verhalten in Glimmer 2 nicht funktioniert (obwohl ich es vielleicht einfach übersehen habe).

vermuten, dass dies andere überraschen könnte, wenn es als Teil von Ember 2.10 landet, insbesondere weil die damit verbundene Veraltungswarnung ausdrücklich besagt, dass das Verhalten bis 3.0 unterstützt wird. Ich glaube nicht, dass ich irgendwo gesehen habe, dass dieses Verhalten in Glimmer 2 nicht funktioniert (obwohl ich es vielleicht einfach übersehen habe).

Ja, wir müssen hier einige Nachrichten / Details verbessern.

Ich sehe, das hat es in die Version 2.10 geschafft. Wird dies im Blogbeitrag zur Version 2.10 erwähnt?

Dies wurde im Blog-Beitrag 2.10 nicht erwähnt und überraschte mich, da die Veraltungswarnung zuvor besagte, dass es, wie oben erwähnt, bis 3.0 unterstützt wird.

Ich habe ein Nutzungsmuster, das davon betroffen ist. Ich bin mir sicher, dass das Problem an meinem Nutzungsmuster liegen muss und nicht an dieser speziellen Änderung, aber ich würde mich über einen Beitrag dazu freuen, was ein gutes alternatives Nutzungsmuster wäre!

Grundsätzlich habe ich eine Seite, die einen filterbaren Datensatz anzeigt, und um dies zu erreichen, verwende ich einen von Ember berechneten Wert, um die Daten basierend auf dem Wert mehrerer Abfrageparameter auf der Seite zu filtern. Um jedoch zu verhindern, dass ungültige Eingaben (z. B. keine Buchstaben oder Zahlen) durch Benutzereingaben zu Abfrageparametern hinzugefügt werden, habe ich das folgende Muster:

 filteredModel: Ember.computed('model', /*list of individual query params*/, function(){
    let model = this.get('model').filterBy('pdf.pdf_path.url'); //removes all records that don't have a pdf uploaded
    this.get('queryParams').forEach((filter)=> { // for each possible filter
      if ((this.get(filter).length > 0)) { //if the filter has content...
        //guardian pattern to prevent invalid inputs
        let valid = new RegExp('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$');
        while (this.get(filter).length > 0 && !valid.test(this.get(filter))){
          this.set(filter, this.get(filter).slice(0,-1));
        }
        //block of code where the model gets filtered
        //...
        //...
    });
    return model;
  }),

Wenn ich also berechnet habe, wie das gefilterte Modell aussehen sollte, ziehe ich, wenn einer der Filterwerte ungültige Zeichen enthält, das letzte Zeichen ab, bis es gültig wird. Hat jemand einen Vorschlag für eine sauberere Methode zur Überprüfung der Gültigkeit dieser Eingaben?

Auch das hat uns überrascht - zumal wir keine Warnmeldungen gesehen haben, als die App mit 2.9 lief. Wenn wir auf 2.10 aktualisieren, wird die Anwendung nicht geladen und verweist auf diesen Fehler. Hat noch jemand dieses Verhalten gesehen?

@revanar Ich könnte hier völlig daneben sein, aber es sieht so aus, als ob Ihr CP eigentlich zwei verschiedene Dinge ist: ein CP zum Zurückgeben des gefilterten Modells und eines zum Aktualisieren der Filter. Ich würde das Aktualisieren des Filterteils in ein Observable verschieben. Oder, wenn dies eine Komponente ist und Sie die Abfrageparameter an die Komponente übergeben, würde ich die Logik in den didReceiveAttrs Hook verschieben. Aus meiner Erfahrung mit dem Fehler "Backtracking Rerender" denke ich, dass das Verschieben der Operation set aus dem CP den Fehler beheben sollte.

Auch damit tun wir uns schwer. Ich habe viele der Probleme behoben, aber ein Fall, in dem wir diesen veralteten Fehler sehen, ist verwirrend.

Assertion Failed: You modified transitioningIn twice on <app<strong i="6">@component</strong>:link-to::ember1159> in a single render.

Es sieht so aus, als ob ein Fehler auftritt, weil eine interne Eigenschaft von ember mehr als einmal aktualisiert wird. Leider reproduziert es sich während unserer Selen-Tests, so dass es schwierig zu debuggen ist (der Selen-Treiber verhindert, dass Entwicklungstools während des Tests funktionieren). Ich habe mindestens eine Instanz des Problems auf einen Controller.transitionToRoute-Aufruf zurückverfolgt, der am Ende unseres Anmeldevorgangs getätigt wurde, aber es scheint in verschiedenen Szenarien aufzutreten.

Ich bin mir nicht sicher, wie ich bei der Fehlerbehebung vorgehen soll.

@chancancode erwähnte ein Feature-Flag zum Deaktivieren dieses veralteten Fehlers, aber ich sehe keine Informationen dazu unter https://github.com/emberjs/ember.js/blob/master/FEATURES.md. Kennt jemand die Flagge?

Auch für unsere ember 2.10-Migration ist dies der Hauptschmerzpunkt. Wir haben auch viele dieser Probleme behoben. Es scheint, dass es keine Single/Clear Cut-Strategie gibt, um diese Fehler zu beheben. Je nach Anwendungsfall haben wir folgende Ansätze ausprobiert

  1. Code einpacken in Ember.run.next
  2. Verschieben Sie jeden setter Code von computed properties in Lebenszyklus-Hooks oder in event handlers , wo immer dies möglich ist.
  3. Ausprobieren verschiedener Kombinationen von Lifecycle-Hooks für Komponenten

Auch damit haben wir große Schwierigkeiten. In den letzten Jahren haben wir eine ganze Reihe von Dropdown-Menüs angesammelt, die automatisch das erste Element eines bestimmten Typs aus dem Cache des ember-Datenspeichers auswählen. Dies führt zu einem erneuten Rendern, da einige Teile der Seite von der Dropdown-Auswahl gesteuert werden. Ich bin mir nicht ganz sicher, was ich tun soll, da ich nicht denselben Code wiederholen möchte, um das erste Element der Liste auf jeder Seite, auf der die Dropdowns verwendet werden, auszufüllen und auszuwählen.

@scottmessinger Danke für das Feedback. Die Verwendung einer Komponente hat am Ende ziemlich gut geklappt. Ich habe es geschafft, den Backtracking-Fehler zu beseitigen, und ich denke, mein Code ist dafür ein bisschen sauberer.

Kris Selden hat einen nützlichen Tipp zum Debuggen dieser:

screen shot 2016-12-12 at 13 10 44

Ich habe die Schritte hier genauer beschrieben: https://github.com/GavinJoyce/backtracking/pull/1#issuecomment -266427152

Ich arbeite an der Verbesserung der Backtracking-Assertion-Nachricht . Ich habe einen 2.10.2-with-improved-backtracking-assertion Build erstellt, der diese besseren Nachrichten enthält:

Vor:

Sie haben message.message_goal.description zweimal auf <(subclass of Ember.Model):ember3486> in einem einzigen Rendering geändert. Dies war in Ember 1.x unzuverlässig und langsam und wird nicht mehr unterstützt. Weitere Informationen finden Sie unter https://github.com/emberjs/ember.js/issues/13948 .

Nach:

Sie haben message.message_goal.description zweimal auf <(subclass of Ember.Model):ember3486> in einem einzigen Rendering geändert. Es wurde in component:message-edit-expanding-container-component gerendert und in component:rules/predicate-date-value-component modifiziert. Dies war in Ember 1.x unzuverlässig und langsam und wird nicht mehr unterstützt. Siehe Nr. 13948 für weitere Details.

Ich habe noch ein paar Dinge zu tun, bevor es fertig ist, aber es wäre wirklich nützlich, wenn ein paar Leute dies in ihrer App ausprobieren würden. /cc @fivetanley , @bryanhickerson , @revanar , @phammers , @scottmessinger , @tharrington1 , @manimis902 , @jakesjews , @elwayman02. Bitte informieren Sie mich, wenn Sie in Ihrer App nicht-ideale Assertion-Nachrichten sehen.

Um es auszuprobieren, aktualisieren Sie Ihre bower.json , um die ember-Abhängigkeit wie folgt einzuschließen:

{
  "name": "backtracking",
  "dependencies": {
    "ember": "intercom/ember#2.10.2-with-improved-backtracking-assertion",
    "ember-cli-shims": "0.1.3"
  },
  "resolutions": {
    "ember": "2.10.2-with-improved-backtracking-assertion"
  }
}

Sie können eine Beispielanwendung sehen, die diesen Build hier ausführt :

Ich habe gerade einen 1.11.0-Canary-Build geschnitten

Ist das ein Tippfehler?

@rwjblue danke, das war ein Tippfehler. Aktualisiert

@GavinJoyce danke, dass

@Dhaulagiri Bei Interesse organisiere ich gerne irgendwann eine Bildschirmfreigabe und gehe auf dein genaues Problem ein. Ich möchte, dass die Fehlermeldungen so hilfreich wie möglich sind, und es wäre nützlich, Ihren Fall zu prüfen (und ich werde wahrscheinlich in der Lage sein, die Ursache zu identifizieren).

FWIW Ich habe ein weiteres Problem in diesem Zusammenhang gefunden: https://github.com/alexspeller/ember-cli-active-link-wrapper/issues/25

Habe auch den Branch von ich versuchte, einen Fehler zu finden, um ein Tabs-Steuerelement auf ember-paper zu bringen (siehe oben PR). Leider scheint es, dass ich in meinem Fall auch Hinweise auf Komponenten bekomme, die nicht beteiligt zu sein scheinen.

@bjornharrtell hast du einen ember-paper-Zweig, den ich ausprobieren kann?

^ Wir haben uns ein wenig Zeit genommen, um in die Themen von ember-paper einzutauchen (https://github.com/miguelcobain/ember-paper/pull/590). Es scheint, dass:

  • die neuen Fehlermeldungen waren nützlicher als die aktuellen
  • sie waren nicht perfekt, da sie nicht gut mit den gewonnenen Inhalten umgehen konnten. (die Komponente, die {{yield}} enthielt, wurde als nützliche Quelle gemeldet, aber nicht so nützlich, wie sie vielleicht sein könnte)

Es kann ein Fehler mit dem Addon sein oder nicht, aber ich bin auf diesen Fehler in https://github.com/DockYard/ember-one-way-controls/issues/136 gestoßen

Ich habe ein Problem gefunden.
Ich verwende ein Mixin mit Einstiegspunkten, um die gleiche Eigenschaft für den Controller zu aktualisieren, mit dem es gemischt wurde. Dies sind definitiv unterschiedliche Eigenschaften, da sie einfach zu verschiedenen Controllern gehören und die Assertion fehlschlägt und js blockiert.
Ich habe das Mixin getestet, indem ich es in ein paar Controller ausgepackt habe und einen Übergang zwischen den Routen zur Reproduktion vorgenommen habe - es wurde nicht reproduziert.

Im Moment versuche ich, Mixins loszuwerden, also werde ich sie einfach töten und einen Workaround erstellen.

Ich glaube, ich habe einen gültigen Anwendungsfall, bei dem wir dieses Problem beim erneuten Rendern sehen. In unserer App haben wir eine Schaltfläche, die einen Status enthält (OK, Validierung, Warnung, Fehler). Es ist eine Komponente, die den aktuellen Status anzeigt, validiert, wenn bestimmte Dinge passieren, und basierend auf dem Ergebnis der Validierung oder Aktivierung verschiedene Dinge anzeigt (Spinner, anderer Schaltflächentext, andere Schaltflächenklasse).

Wir überprüfen die Validierung auf init() und legen basierend auf der Antwort der Validierung den entsprechenden Schaltflächenstatus fest. Die Schaltflächenklasse ist eine berechnete Eigenschaft, die die entsprechenden Klassen basierend auf dem Schaltflächenstatus festlegt. Da dies bei init auftritt, scheint dieser Fehler ausgelöst zu werden, da wir bei der Instanziierung mit dem Status ok beginnen und dann zur Validierung übergehen, während wir die Version und den Endzustand basierend auf der Antwort validieren. Der Anwendungsfall selbst erscheint jedoch vernünftig und daher erscheinen auch die stattfindenden Zustandsänderungen vernünftig.

@tundal45 könnten Sie möglicherweise eine Twiddle- oder Beispiel-App erstellen, die zeigt, was Ihrer Meinung nach ein falscher Fehler ist?

@Blackening999 @tundal45 können Sie Ihren Anwendungsfall in einen

@chancancode @Blackening999 Ich werde versuchen, bald einen hier zu posten. Danke für eine schnelle Antwort.

@chancancode https://ember-twiddle.com/936d549b5625b0cf4f3c945d0ed04d3b?openFiles=components.button-with-state.js wäre der Twiddle, aber ich sehe den Fehler nicht, den ich in der App sehe, also könnte es etwas anderes sein, das verursacht es.

Ich sehe dies bei mehreren berechneten Eigenschaften, von denen eine einfache Ember.computed.or . Da in diesem Fall keiner der Vorschläge von @manimis902 anwendbar ist, was wäre eine geeignete Problemumgehung?

Wie @tharrington1 erwähnen, wo ist das Flag für die von @chancancode erwähnte

@cbou soweit ich weiß existiert diese Flagge nicht

Ich war mir nicht ganz sicher, wie ich mit diesen veralteten Hinweisen umgehen soll, und bin mir auch nicht sicher, ob mein Fix gültig war/ist, aber ich habe eine AJAX-Anfrage im init() Komponenten-Hook durchgeführt, die eine Wertänderung in einem anderen auslöste Service-Eigenschaft (um zu verfolgen/zu zeigen, wenn auf den Remote-Server zugegriffen wird).

Ich habe meinen AJAX-Anforderungscode vom init() Komponenten-Hook in den didRender() Komponenten-Hook verschoben und es scheint, dass mein Hinweis auf die Einstellung behoben wurde.

@lvl99 Ich habe das gleiche gemacht.

Wir bemühen uns, unser Enterprise-Projekt von 2.3 auf Ember 2.12 zu aktualisieren. In unserem Projekt haben wir ein Validierungs-Add-On und ein separates Formularkomponenten-Add-On. Das Validierungs-Add-on funktioniert auf Ember.components, um Validierungsfehler zu generieren, und das Formularkomponenten-Add-on zeigt die vom Validierungs-Add-on erzeugten Fehler über einen Helfer an. Die Add-Ons sind viel zu kompliziert, um Quellcode zu teilen; Daher haben wir den folgenden Twiddle erstellt , um den Fall zu veranschaulichen, mit dem wir konfrontiert sind.

Das angegebene Beispiel enthält zwei Komponenten ( person-detail und address-detail ), die dafür verantwortlich sind, ihre eigenen Validierungsfehler zu generieren. Die von address-detail generierten Validierungsfehler werden über eine Aktion, die innerhalb der berechneten Eigenschaft errors ausgelöst wird, auf die enthaltende Komponente ( person-detail ) kaskadiert. Von jeder Komponente erzeugte Fehler werden innerhalb einer error-displayer Komponente mit Hilfe des Helfers error-formatter angezeigt. Der bereitgestellte Code funktioniert wie erwartet, wie Sie sehen können.

Jedoch; Wir haben eine veraltete Warnung wie folgt: DEPRECATION: The Fehler property ofis an Ember.Binding connected to validatable.errors.name , but Ember.Binding is deprecated. Consider using an alias computed property instead. [deprecation id: ember-metal.binding] See http://emberjs.com/deprecations/v2.x#toc_ember-binding for more details. Um das zu vermeiden; Bitte gehen Sie in den Helfer error-formatter und kommentieren Sie Zeile 9 aus und kommentieren Sie Zeile 8 aus, damit wir wie in der Warnerklärung vorgeschlagen vorgehen.

Jetzt kommen wir zu den berüchtigten Assertion Failed: You modified "error" twice on <Ember.Object:ember338> in a single render. It was rendered in "component:error-displayer" and modified in "component:error-displayer". This was unreliable and slow in Ember 1.x and is no longer supported. See https://github.com/emberjs/ember.js/issues/13948 for more details. Wir verstehen, warum wir diesen Fehler erhalten; weil Aktionsauslösung innerhalb von address-detail s errors berechnete Eigenschaft zu einer Neuberechnung der errors berechneten Eigenschaft von person-detail und bereits gerenderte Inhalte diesen Fehler verursachen . Das möchten wir gerne lernen:

  1. Ember.Binding vs Ember.computed.alias funktioniert in Bezug auf die Neuberechnungsphase (Neurendering) sicherlich ganz anders. Was ist der genaue Unterschied? Der Vorschlag, letzteren als Ersatz für den ersten zu verwenden, scheint Code zu brechen; zumindest für unseren fall.
  2. Ist das Auslösen einer Aktion innerhalb einer berechneten Eigenschaft ein Problem? Falls ja; Was sind mögliche Vorschläge, um es zu vermeiden?
  3. Wir erwägen, eine Aktion einzuschließen, die mit einer Ember.run.scheduleOnce('afterRender', ...) Anweisung ausgelöst wird. Ist das der richtige Weg?
  4. Schließlich; Bitte gehen Sie zurück zum Breaking Code und geben Sie etwas in ein beliebiges Feld ein; und überraschenderweise werden die Komponenten mehrmals neu gerendert; wir vermuten, dass dies mit einem Fehler zusammenhängt.

FWIW, ich habe gesehen, dass meine Komponenten in einigen Fällen häufiger neu gerendert wurden, als ich es erwarten würde. Das Aufspüren der Ursache eines erneuten Renderns ist ziemlich zeitaufwändig, da es oft mit einem Runloop synchronisiert wird. Ich würde gerne wissen, ob es in diesem Bereich Verknüpfungen oder Debugging-Tricks gibt.

Gibt es eine Möglichkeit, diese Behauptung bei Debugbuilds abzufangen oder zu unterdrücken? Wir haben dies über Refactorings wie oben beschrieben an den meisten Stellen aufgespürt und behoben, aber es gibt 1 oder 2, die ziemlich hartnäckig sind. In einem bestimmten Fall zerstören wir ein Objekt und gehen dann über. Das zerstörte Objekt (auf unserer API) sendet eine Pusher-Benachrichtigung, um mehrere weitere Objekte zu entladen/zu zerstören.

In Produktions-Builds ist das erneute Rendern kein Problem, da wir nur das Objekt zerstören und dann sowieso weggehen (also die gesamte Route abgerissen wird). Die Behauptung bei Dev-Builds ist jedoch ziemlich frustrierend, da eine Aktualisierung erforderlich ist, um die Site wiederherzustellen. Ich verstehe, warum wir den Fehler bekommen, aber es ist in diesem Fall eine ziemlich komplizierte Umgestaltung, um ihn zu vermeiden, und auf jeden Fall spielt es keine Rolle, da die gesamte Route zerstört wird. Gibt es eine Möglichkeit, dies abzufangen / zu unterdrücken / in eine Warnung zu ändern? Ich habe Try/Catch sowie den Fehlerhandler der Route versucht, aber keiner hat es aufgegriffen.

@feanor07 Senden einer Aktion von innen heraus, die den

Grundsätzlich haben Sie eine zyklische Abhängigkeit und müssen Daten nach unten fließen. Geben Sie den Fehler nicht wieder, bevor Sie die Validierung ausgeführt haben. Sie können in einer übergeordneten Komponente validieren, die das Modell und Fehler ausgibt, um das Formular innerhalb seines Blocks zu rendern.

@feanor07 Ember.run.scheduleOnce... hat nicht funktioniert, aber das Hinzufügen von nur einem Ember.run.schedule("afterRender", () => { ... }); zur Eigenschaft set zuerst vom Stack-Trace angezeigt wurde, eliminierte viele Fehlermeldungen, die nach der ersten kaskadiert wurden.

@neilthawani , das den Fehler möglicherweise verbirgt, aber das Problem nicht unbedingt behebt. Der Fehler soll darauf hinweisen, dass Sie einen Wert zweimal festlegen, obwohl Sie ihn wahrscheinlich nur einmal festlegen sollten. Indem Sie einen der set in schedule einfügen, verzögern Sie nur den zweiten Satz, sodass er in einer anderen Runloop stattfindet. Sie haben das Kernproblem des zweimaligen Renderns nicht behoben, wenn Sie nur einmal rendern müssen, sondern haben Ember nur dazu gebracht, nicht zu wissen, dass es ein Problem gab, da die Renderings jetzt in separaten Runloops stattfinden.

@elwayman02 Äh oh. Vielen Dank. Im Grunde hat es den Punkt völlig verfehlt.

Bearbeiten: Nachdem ich damit zu kämpfen hatte, fügte ich ein paar mehr afterRenders als mir lieb war. Wir haben einen click Handler in einer unserer Datenvisualisierungskomponenten, der eine QuickInfo umschaltet. Das Setzen des isDisplaying Flags innerhalb eines Ember.run.schedule("afterRender", () => { ... }); ermöglichte es uns, das eigentliche Problem zu debuggen, das eigentlich ein Zurückverfolgen im Controller war, der sowohl die Datenvisualisierungskomponente als auch die Tooltipkomponente aufrief.

tl;dr: Ich habe es nicht drin behalten (hatte auch einmal einen Maximum call stack size exceeded Fehler), aber es war hilfreich für das Debuggen, bis das eigentliche Problem aufgedeckt wurde.

PSA für jemand anderes gerade jetzt ein Upgrade: Die verbesserte „Rückzieher Wieder machen“ Assertionsfehler von @GavinJoyce oben erwähnt ist tatsächlich enthalten in Ember 2.11. Es wurde auch vorgeschlagen, dass es hilfreich sein könnte, direkt zu 2.11 zu springen.

Leute, ich brauche Hilfe: Dieser Fehler tritt auf, wenn ich versuche, eine Modelleigenschaft zu verwenden, die zu einer anderen "gehört". Ich habe ein leeres Projekt erstellt und es zeigt immer noch dasselbe. Was mache ich falsch?

Außerdem verwende ich in meinem Back-End .Net Core mit JSON-API .Net Core (https://github.com/Research-Institute/json-api-dotnet-core) - befolgen Sie die Anweisungen.

Das UI-Rendering ist an dieser Stelle unterbrochen, aber die Daten werden geladen und ich kann die gewünschten Werte sehen.

    // Profile Model:
    import DS from 'ember-data';
    export default DS.Model.extend({
        'firstName': DS.attr(),
        'lastName': DS.attr(),
        'applicationUser': DS.attr(),
        'contactProfile': DS.belongsTo('address', {
            async: true
        }),
        'companyProfile': DS.belongsTo('address'),
        'companyMailingAddress': DS.belongsTo('address'),
        "companyPhysicalAddress": DS.belongsTo('address')
    });

    // Address Model:
    import DS from 'ember-data';
    export default DS.Model.extend({
        'address1': DS.attr(),
        'address2': DS.attr(),
        'city': DS.attr(),
        'state': DS.attr(),
        'zipCode': DS.attr(),
        'country': DS.attr(),
        'website': DS.attr(),
        'phoneNumber1': DS.attr(),
        'phoneExtension1': DS.attr(),
        'phoneNumber2': DS.attr(),
        'phoneExtension2': DS.attr(),
        'email': DS.attr(),
    });
    // Adapter settings
    import DS from 'ember-data';

    export default DS.JSONAPIAdapter.extend({
        namespace: 'api/json',
    });
    DS.JSONAPISerializer.reopen({
        keyForAttribute(key) {
            return key;
        },
        keyForRelationship(key) {
            return key;
        }
    });
    // Route
    import Ember from 'ember';

    export default Ember.Route.extend({
        model() {
            return Ember.RSVP.hash({
                profile: this.store.findRecord('profile', 1)
            });
        }
    });

    // Template
   {{model.profile.contactProfile.address1}}

und die Fehlermeldung bekomme ich:
Assertion fehlgeschlagen: Sie haben "model.profile.contactProfile" zweimal geändert am@model:profile::ember543:1> in einem einzigen Rendering. "Es wurde in übertragen : Brennstoffe-glut / intern / profile / template.hbs Vorlage " und modifizierte in " Vorlage: Brennstoffe-glut / intern / profile / template.hbs ". Dies war in Ember 1.x unzuverlässig und langsam und wird nicht mehr unterstützt. Weitere Informationen finden Sie unter https://github.com/emberjs/ember.js/issues/13948 .

PS: Ich habe versucht, die Ember.computed-Methode zu verwenden, um die Eigenschaft zu erhalten, und das scheint zu funktionieren. Ist dies erforderlich?

Update: Ich habe auch festgestellt, dass die Daten innerhalb eines {{#each}}-Helfers problemlos geladen werden, jedoch nicht direkt auf der Vorlage.

@lbarsukov
Vielleicht hängt es mit https://github.com/emberjs/data/issues/5023 zusammen, wo ein Backtracking-Re-Rendering durch Beziehungen in Ihrer jsonapi-Antwort mit einer links Eigenschaft verursacht wird.

Dies war das Problem für mich, das nach Ember Data 2.13.2 begann. Versuchen Sie es mit ember-data: 2.13.2, um zu sehen, ob dies Ihr Problem löst.

@daniel-de-wit Daumen hoch für den Meister hier - das funktioniert tatsächlich. Es tut jetzt was ich brauche und bin damit zufrieden.

@lbarsukov @daniel-de-wit Wir haben eine neue Version von ember data veröffentlicht , die dieses Problem behebt.

@lbarsukov Ich denke, das hat mit Ihren definierten Beziehungen zu tun. Es besteht eine gute Chance, dass einer (oder mehrere) der belongsTo ein hasMany .

Angenommen, Sie haben zwei Modelle, Frage und Antwort. Wenn Sie 10 Antworten auf die Frage zurückgeben, aber jeder Frage-Serializer auf seine Antwort verweist, müssen Sie die Beziehung richtig definieren.

// Question Model:
    export default DS.Model.extend({
        'answers': DS.hasMany('answers'), // if you never reference question.answers you can omit this
        ...
    });

// Answer Model:
    export default DS.Model.extend({
        'question': DS.belongsTo('question'),
        ...
    });

Wenn die Daten mehrere Frage-Antwort-Paare definieren und eine 1:1-Beziehung erwarten, wo keine vorhanden ist, wird daraus geschlossen, dass die Frage mitten im Rendering geändert wurde.

Aus dem ersten Beitrag wurden einige Hooks erwähnt:

Dies ist ein ziemlich extremes Beispiel, aber es veranschaulicht das Problem. Neben init, didInitAttrs, didReceiveAttrs, willInsertElement und willRender geschieht auch synchron während des Rendervorgangs. Darüber hinaus ist Backtracking häufig ein Problem, das sich aus dem Verhalten von bidirektionalen gebundenen Eigenschaften ergibt.

Warum funktionieren didInsertElement und didRender Hooks wie ein Zauber, aber die anderen Hooks schlagen mit dem twice render Fehler fehl?

@BenjaminHorn @ Blackening999 @Dhaulagiri @DingoEatingFuzz @ Gaurav0 @GavinJoyce @Redsandro @TRMW @ Turbo87 @aklkv @alidcastano @backspace @bdiz @bgentry @bjornharrtell @bryanhickerson @buschtoens @caseklim @cbou @chancancode @danaoira @ daniel-de-Witz @fivetanley @fotinakis @gabrielgrant @ghost @jakesjews @janmisek @joukevandermaas ist das immer noch ein Thema, vielleicht sollten wir schließen, was denkst du?

Ich habe alle Instanzen des Fehlers in meiner App behoben.

Jedes Mal, wenn ich darauf gestoßen bin, konnte ich die Dinge neu anordnen, damit es nicht mehr passiert, also denke ich, dass es in Ordnung ist, zu schließen.

Ja, bitte schließen

Ende einer Ära

👍

Es tut mir leid, ein altes Problem anzusprechen.

Sagen wir zum Beispiel, ich rendere

{{this.myBool}}

und der Fehler ist Error: Assertion Failed: You modified "myBool" twice

Ich kann den Fehler beheben, indem ich ihn in Folgendes ändere:

{{if this.myBool true false}}

Ebenso, wenn eine Klassennamenbindung das Problem verursacht

Ich kann mich ändern:

classNameBindings: ['myBool']

zu

classNameBindings: ['myBool:yes:no']

Wenn ich die Warnung so zum Schweigen bringen kann, warum kann Ember sie dann nicht für mich erledigen?

Hier ist der Democode, den ich verwendet habe:

https://ember-twiddle.com/db7f6e382bd0b1de91447881eebb62a5?openFiles=templates.components.my-component.hbs%2C

Keines dieser Dinge "behebt" das Problem. Entweder haben Sie in den Produktionsmodus gewechselt oder es gibt Fehler im Assertions-/Erkennungscode. In jedem Fall müssen Sie die Seite reparieren, die den Wert zuweist/festlegt, nicht die Seite, die ihn verbraucht.

Okay. Dankeschön. Ich verstehe das in diesem ursprünglichen Beitrag beschriebene Backtracking-Problem, da es ein explizites set

Aber in meinem Demo-Twiddle gibt es, soweit ich sehen kann, kein set .

_Bearbeiten_ Das kam falsch heraus, ich meine damit, dass kein set aus einem _nachfolgendem_ Teil der Vorlage stammt, wie es im Beispiel der Fall ist

Hm, ich bekomme den Fehler nicht im Handumdrehen, wie ist die Reihenfolge der Klicks, die ich tun soll?

Klicken Sie auf Öffnen und dann auf Schließen. Aber die Schließen-Schaltfläche der erhaltenen untergeordneten Komponente, nicht die der übergeordneten.

Ich sehe, das Problem ist, dass beim Teardown focusOut für die Komponente aufgerufen wird, die set für eine bereits gerenderte Eigenschaft aufruft. Ich bin mir nicht 100% sicher, wie die Komponente den Fokus und die Timing-Semantik verliert. Ich bin mir ziemlich sicher, dass die von Ihnen ausprobierten Variationen nur das Tracking-System verwirren und das zugrunde liegende Problem verschleiern. Lassen Sie uns das in einer neuen Ausgabe verfolgen? Ich bin mir nicht sicher, ob es ein gültiges Problem ist, aber lassen Sie uns die Untersuchung dort durchführen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen