Ember.js: [Glimmer 2] "Повторный рендеринг с возвратом" теперь является утверждением.

Созданный на 29 июл. 2016  ·  63Комментарии  ·  Источник: emberjs/ember.js

Повторный рендеринг с обратным отслеживанием относится к сценарию, в котором в середине процесса рендеринга вы изменили что-то, что уже было отрисовано.

Например:

{{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');
  }  
});

Как видите, к моменту создания и визуализации компонента foo-bar мы уже использовали значение foo из родительского контекста для заполнения {{foo}} curly. Однако в своем конструкторе он пытался изменить то же значение, следовательно. «возврат».

Это довольно крайний пример, но он иллюстрирует проблему. Помимо init , didInitAttrs , didReceiveAttrs , willInsertElement и willRender также происходят синхронно во время процесса рендеринга. Кроме того, возврат с возвратом часто является проблемой, связанной с поведением свойств с двусторонней привязкой.

Такое поведение всегда было ненадежным, но частично поддерживалось устареванием (начиная с 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

Начиная с версии 1.13, Ember поддерживал это, немедленно выполняя второй повторный рендеринг при обнаружении отката (а затем повторял, пока система не стабилизировалась). Эта стратегия сама по себе может стать источником проблем с производительностью. В крайних случаях это может вызвать бесконечный цикл.

В Glimmer 2, несмотря на то, что дополнительный повторный рендеринг обходится относительно дешево, дополнительных учетных записей для обнаружения отката set нет. Одним из преимуществ системы Glimmer 2 является то, что ей не нужно с нетерпением настраивать наблюдателей для отслеживания изменений. Кроме того, некоторые оптимизации в Glimmer 2 позволяют системе пропускать обход поддеревьев, когда она знает, что внутри ничего не изменилось.

Вместе эти факторы означают, что мы не можем легко обнаружить эти обратные прослеживания set s (или было ли что-то «уже обработано» или нет) без выполнения большого количества дополнительных учетных записей и преднамеренного отказа от этих оптимизаций.

Мы уже написали код для поддержки этого, но из-за и без того ненадежного характера функции и (очень значительных) затрат на ведение бухгалтерского учета мы не решаемся автоматически включать их для всех, не зная, нужна ли она еще.

В качестве компромисса в настоящее время мы выполняем обнаружение только в режиме разработки и превратили сообщение об устаревании в утверждение режима разработки (серьезная ошибка). В производственном режиме код обнаружения удаляется, и обратное отслеживание не работает.

Мы сохранили возможность поддержки этой функции (без утверждения) в кодовой базе за вторым флагом функции. Код постоянно тестируется на CI, однако по умолчанию отключен до тех пор, пока у нас не будет достаточно информации об использовании для определения следующих шагов.

Если вы считаете, что у вас есть шаблоны использования, на которые это влияет, опишите как можно больше подробностей о своем сценарии ниже. Вполне возможно, что могут быть альтернативы и / или целевые решения, которые мы можем использовать, которые не требуют полного изменения движка. Поэтому было бы полезно, если бы вы предоставили справочную информацию и контекст своего использования, а не просто показывали нам небольшие фрагменты кода из своей кодовой базы.

Ember 2.10 Inactive

Самый полезный комментарий

Это не было упомянуто в сообщении блога 2.10 и застало меня врасплох, поскольку в предупреждении об устаревании ранее говорилось, что он будет поддерживаться до версии 3.0, как упоминалось выше.

Все 63 Комментарий

К вашему сведению, в нашем приложении были некоторые из этих предупреждений. В частности, мы обновили некоторые свойства службы в init компонента, что заставило бы что-то еще на странице отображаться по-другому.

Это предупреждение очень просто исправить, запланировав изменение свойства в следующем цикле выполнения. Мне потребовался ~ час, чтобы отследить и исправить все предупреждения в нашем (довольно большом) приложении. Хотя это технически критическое изменение, я согласен с вашей оценкой, даже если это потребовало от меня дополнительной работы.

@fivetanley, улучшающий сообщение об ошибке, звучит хорошо. Я знаю, что у @krisselden и @stefanpenner есть рабочий процесс для отслеживания этих проблем, возможно, они могут помочь вам дать какие-то указания по этому

@joukevandermaas run.next () - не лучшее исправление для этой ошибки, хотя я понимаю, если вы переполнены этими ошибками, зачем вам туда идти. Лучше всего попытаться понять, почему обратный поток данных делает недействительными то, что уже отображено.

Вероятно, если вы установите реквизиты для службы, которые можно внедрить в любой компонент, это увеличивает шансы того, что этот набор сделает недействительным то, что уже было отрисовано. В общем, шаблон должен заключаться в том, что set () используется только во внутреннем состоянии во время обработчиков рендеринга, не привязан к вводу или службам и / или set () используется для события, состояние ввода должно устанавливаться по времени рендеринга материала.

@joukevandermaas run.next () - не лучшее исправление этой ошибки,

это вызовет проблемы с производительностью, так как glimmer2 в этом случае сообщает, что «происходит дублирование работы, вам действительно не нужно этого, если вы хотите производительное приложение». Там, где раньше, Ember поглощал это, но приводил к значительному снижению производительности.

У нас есть еще кое-что, что нужно сделать для обмена знаниями ... В конечном итоге мы считаем, что это здоровый путь вперед для приложений. Но мы должны убедиться, что у всех есть инструменты + знания, которые могут принести пользу :)

Как человек, который относительно внимательно следит за развитием Ember (твиттер, здесь, на github, в списках рассылки и т. Д.), Эта проблема подкралась ко мне, поэтому я подозреваю, что это может застать других врасплох, если появится как часть Ember 2.10, особенно потому, что связанное с ним предупреждение об устаревании конкретно указывает, что поведение будет поддерживаться до версии 3.0. Я не думаю, что я где-нибудь видел, чтобы это поведение не сработало в Glimmer 2 (хотя я, возможно, просто пропустил это).

подозреваю, что это может застать других врасплох, если появится как часть Ember 2.10, особенно потому, что предупреждение об устаревании, связанное с ним, конкретно указывает, что поведение будет поддерживаться до 3.0. Я не думаю, что я где-нибудь видел, чтобы это поведение не сработало в Glimmer 2 (хотя я, возможно, просто пропустил это).

да, нам нужно улучшить некоторые сообщения / детали здесь.

Я вижу, что это вошло в выпуск 2.10. Будет ли это упомянуто в сообщении блога о выпуске 2.10?

Это не было упомянуто в сообщении блога 2.10 и застало меня врасплох, поскольку в предупреждении об устаревании ранее говорилось, что он будет поддерживаться до версии 3.0, как упоминалось выше.

У меня есть схема использования, на которую это влияет. Я уверен, что проблема должна заключаться в моем шаблоне использования, а не в этом конкретном изменении, но мне хотелось бы получить информацию о том, какой будет хороший альтернативный шаблон использования!

По сути, у меня есть страница, которая показывает фильтруемый набор данных, и для этого я использую вычисленное значение Ember для фильтрации данных на основе значения нескольких параметров запроса на странице. Однако, чтобы предотвратить добавление неверных входных данных (например, не букв или цифр) в параметры запроса из пользовательского ввода, у меня есть следующий шаблон:

 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;
  }),

По сути, когда я вычислял, как должна выглядеть отфильтрованная модель, если в каком-либо из значений фильтра есть недопустимые символы, я удаляю последний символ, пока он не станет действительным. Есть ли у кого-нибудь предложение более чистого способа проверки действительности этих входных данных?

Это также застало нас врасплох - особенно потому, что мы не видели никаких предупреждающих сообщений, когда приложение работало с версией 2.9. При обновлении до 2.10 приложение не загружается и ссылается на эту ошибку. Кто-нибудь еще видел такое поведение?

@revanar Я мог бы быть здесь полностью отключен, но похоже, что ваш CP - это на самом деле две разные вещи: один CP для возврата отфильтрованной модели и один для обновления фильтров. Я бы переместил обновление части фильтров в наблюдаемое. Или, если это компонент, и вы передаете ему параметры запроса, я бы переместил логику в ловушку didReceiveAttrs . Исходя из моего опыта столкновения с ошибкой «повторного рендеринга с возвратом», я думаю, что перемещение операции set из CP должно устранить ошибку.

У нас тоже тяжелые времена с этим. Я исправил множество проблем, но один случай, когда мы наблюдаем эту ошибку устаревания, вызывает недоумение.

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

Похоже, что сбой происходит из-за того, что внутреннее свойство ember обновляется более одного раза. К сожалению, он воспроизводится во время наших тестов на селен, поэтому его сложно отлаживать (драйвер селена не позволяет инструментам разработчика работать во время выполнения теста). Я отследил по крайней мере один экземпляр проблемы до вызова controller.transitionToRoute, сделанного в конце нашего процесса входа в систему, но, похоже, это происходит в нескольких разных сценариях.

Я не знаю, как продолжить устранение неполадок.

@chancancode упомянул флаг функции для отключения этой ошибки устаревания, но я не вижу никакой информации об этом на https://github.com/emberjs/ember.js/blob/master/FEATURES.md. Кто-нибудь знает, что это за флаг?

Для нашей миграции на ember 2.10 это также основная проблема. Мы также исправляем многие из этих проблем. Кажется, что не существует единой / четкой стратегии для исправления этих ошибок. Мы пробовали следующие подходы, в зависимости от варианта использования.

  1. Код упаковки в Ember.run.next
  2. Перемещение любого кода setter из computed properties в хуки жизненного цикла или в event handlers , где это возможно.
  3. Пробуем разные комбинации крючков жизненного цикла для компонентов

У нас тоже были большие трудности с этим. За последние несколько лет мы накопили изрядное количество выпадающих меню, которые автоматически выбирают первый элемент определенного типа из кеша хранилища данных ember. Это вызывает повторную визуализацию, поскольку некоторые части страницы управляются раскрывающимся списком. Я не совсем уверен, что делать, поскольку я не хочу повторять один и тот же код для заполнения и выбора первого элемента списка на каждой странице, на которой используются раскрывающиеся списки.

@scottmessinger Спасибо за отзыв. Использование компонента оказалось довольно неплохим. Мне удалось избавиться от ошибки обратного отслеживания, и я думаю, что мой код немного чище для нее.

У Криса Селдена есть полезный совет по их отладке:

screen shot 2016-12-12 at 13 10 44

Я описал шаги более подробно здесь: https://github.com/GavinJoyce/backtracking/pull/1#issuecomment -266427152

Я работаю над улучшением сообщения с подтверждением возврата . Я вырезал сборку 2.10.2-with-improved-backtracking-assertion которая включает следующие лучшие сообщения:

До:

Вы дважды изменили message.message_goal.description на <(subclass of Ember.Model):ember3486> за один рендеринг. Это было ненадежно и медленно в Ember 1.x и больше не поддерживается. См. Https://github.com/emberjs/ember.js/issues/13948 для получения более подробной информации.

После:

Вы дважды изменили message.message_goal.description на <(subclass of Ember.Model):ember3486> за один рендеринг. Он был обработан в component:message-edit-expanding-container-component и изменен в component:rules/predicate-date-value-component . Это было ненадежным и медленным в Ember 1.x и больше не поддерживается. См. # 13948 для более подробной информации.

Мне нужно сделать еще несколько вещей, прежде чем он будет готов, но было бы действительно полезно, если бы несколько человек попробовали это в своем приложении. / cc @fivetanley , @bryanhickerson , @revanar , @phammers , @scottmessinger , @ tharrington1 , @ manimis902 , @jakesjews , @ elwayman02. Пожалуйста, дайте мне знать, если вы увидите в своем приложении какие-либо неидеальные сообщения с утверждениями.

Чтобы попробовать это, обновите bower.json чтобы включить зависимость ember следующим образом:

{
  "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"
  }
}

Вы можете увидеть пример приложения, запускающего эту сборку здесь: https://github.com/GavinJoyce/backtracking/pull/10

Я только что вырезал 1.11.0-canary build

Это опечатка?

@rwjblue спасибо, это была опечатка. Обновлено

@GavinJoyce, спасибо, что взяли это на себя! Я попробовал это в нашем приложении, и оно определенно _более_ полезно, чем предыдущее сообщение. К сожалению для нас, это все еще не упрощает решение этой проблемы, потому что свойство, которое он отмечает как изменяемое, явно не изменяется ни в одном месте, указанном в сообщении об ошибке. Я не совсем уверен, почему это так, но мы надеемся углубиться в это в следующем году.

@Dhaulagiri, если вам интересно, я был бы рад организовать когда-нибудь демонстрацию экрана и погрузиться в вашу конкретную проблему. Я очень хочу, чтобы сообщения об ошибках были максимально полезными, и было бы полезно рассмотреть ваш случай (и я, вероятно, смогу помочь определить основную причину).

FWIW Я обнаружил еще одну проблему, связанную с этим: https://github.com/alexspeller/ember-cli-active-link-wrapper/issues/25

Также попробовал ветку @GavinJoyce при попытке найти ошибку в постоянных усилиях по

@bjornharrtell, у вас есть ветка из

^ Нам потребовалось немного времени, чтобы погрузиться в проблемы с тлеющей бумагой (https://github.com/miguelcobain/ember-paper/pull/590). Кажется, что:

  • новые сообщения об ошибках были более полезными, чем текущие
  • они не были идеальными, так как плохо справлялись с полученным контентом. (компонент, содержащий {{yield}} был указан как источник, который был полезен, но не так полезен, как мог бы быть)

Это может быть или не быть ошибкой с аддоном, но я столкнулся с этой ошибкой в https://github.com/DockYard/ember-one-way-controls/issues/136

Я нашел проблему.
Я использую миксин, у которого есть точки входа для обновления того же свойства для контроллера, с которым он был смешан. Это определенно разные свойства, потому что они просто принадлежат разным контроллерам, а утверждение не выполняется и блокирует js.
Я протестировал миксин, развернув его на несколько контроллеров, и сделал переход между маршрутами для воспроизведения - он не воспроизводился.

На данный момент я пытаюсь избавиться от миксинов, поэтому я просто убью его и создам обходной путь.

Я считаю, что у меня есть допустимый вариант использования, когда мы наблюдаем эту проблему повторного рендеринга. В нашем приложении есть кнопка, которая содержит некоторое состояние (нормально, проверка, предупреждение, ошибка). Это компонент, который показывает текущее состояние, проверяет, когда что-то происходит, и на основе результата проверки или активации отображает разные вещи (счетчики, другой текст кнопки, другой класс кнопки).

Мы проверяем валидацию на init() и на основе ответа валидации устанавливаем соответствующее состояние кнопки. Класс кнопки - это вычисляемое свойство, которое устанавливает соответствующие классы в зависимости от состояния кнопки. Поскольку это происходит при инициализации, похоже, что эта ошибка возникает, потому что мы начинаем со статусом ok при создании экземпляра, а затем переходим к проверке, поскольку мы проверяем версию и конечное состояние на основе ответа. Однако сам вариант использования кажется разумным, и поэтому происходящие изменения состояния также кажутся разумными.

@ tundal45 не могли бы вы создать твиддл или образец приложения, которое демонстрирует, что вы считаете неправильной ошибкой?

@ Blackening999 @ tundal45 можете ли вы превратить свой сценарий использования в тупик?

@chancancode @ Blackening999 Я постараюсь в ближайшее время опубликовать его здесь. Спасибо за быстрый ответ.

@chancancode https://ember-twiddle.com/936d549b5625b0cf4f3c945d0ed04d3b?openFiles=components.button-with-state.js будет твидлом, но я не вижу ошибки, которую вижу в приложении, поэтому может быть что-то еще, что вызывает это.

Я вижу это в нескольких вычисленных свойствах, одно из которых - простое Ember.computed.or . Поскольку ни одно из предложений @manimis902 не применимо в этом случае, что может быть подходящим обходным путем?

Как упоминает @ tharrington1, где находится флаг для функции, упомянутой @chancancode ?

@cbou, насколько я знаю, этого флага не существует

Я не был полностью уверен, как обрабатывать эти уведомления об устаревании, и не уверен, что мое исправление было / действительным, но я выполнял запрос AJAX в хуке компонента init() который вызвал изменение значения в другом свойство службы (для отслеживания / отображения доступа к удаленному серверу).

Я переместил свой код запроса AJAX из хука компонента init() хук компонента didRender() и, похоже, он разрешил мое уведомление об устаревании.

@ lvl99 Я сделал то же самое.

Мы очень стараемся обновить наш корпоративный проект до Ember 2.12 с 2.3. В нашем проекте есть надстройка для проверки и отдельная надстройка для компонентов формы. Надстройка проверки работает с компонентами Ember.components для генерации ошибок проверки, а надстройка компонентов формы отображает ошибки, сгенерированные надстройкой проверки, через помощник. Надстройки слишком сложны, чтобы делиться исходным кодом; поэтому мы создали следующий тиддл, чтобы проиллюстрировать случай, с которым мы столкнулись.

Данный пример содержит два компонента ( person-detail и address-detail ), которые несут ответственность за создание собственных ошибок проверки. Ошибки проверки, сгенерированные address-detail , каскадно передаются содержащему компоненту ( person-detail ) посредством действия, инициированного в вычисляемом свойстве errors . Ошибки, сгенерированные каждым компонентом, отображаются в компоненте error-displayer с помощью помощника error-formatter . Как видите, предоставленный код работает так, как ожидалось.

Тем не мение; у нас есть предупреждение об устаревании: DEPRECATION: The error 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. Чтобы этого избежать; войдите в помощник error-formatter и закомментируйте строку номер 9 и раскомментируйте строку номер 8, чтобы мы действовали так, как предлагается в объяснении предупреждения.

Теперь мы подошли к печально известному 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. Мы понимаем, почему мы получаем эту ошибку; потому что запуск действия в пределах address-detail s errors вычисляемого свойства приводит к повторному вычислению вычисляемого свойства errors для person-detail а содержимое, которое уже визуализировано, вызывает эту ошибку . Вот что мы хотели бы узнать:

  1. Ember.Binding vs Ember.computed.alias наверняка работает совершенно по-другому с точки зрения фазы повторного вычисления (повторного рендеринга). В чем точная разница? Предложение использовать последний вместо первого, похоже, нарушает код; по крайней мере, в нашем случае.
  2. Является ли запуск действия из вычисляемого свойства проблемой? Если да; какие возможные предложения, чтобы этого избежать?
  3. Мы рассматриваем возможность обертывания срабатывания триггера действия с помощью оператора Ember.run.scheduleOnce('afterRender', ...) . Это правильный путь?
  4. Наконец-то; пожалуйста, вернитесь к разделу «Код нарушения» и введите что-нибудь в любое поле; и, что удивительно, компоненты повторно визуализируются несколько раз; мы подозреваем, что это могло быть связано с ошибкой.

FWIW, в некоторых случаях я видел, как мои компоненты перерисовываются чаще, чем я ожидал. Отслеживание причины повторного рендеринга занимает довольно много времени, потому что оно часто синхронизируется с циклом выполнения. Я хотел бы знать, есть ли в этой области ярлыки или приемы отладки.

Есть ли способ поймать или подавить это утверждение в отладочных сборках? Мы отследили и исправили это с помощью рефакторов, как описано выше в большинстве случаев, но есть 1 или 2, которые довольно упрямы. В одном конкретном случае мы уничтожаем объект, а затем выполняем переход. Уничтоженный объект (в нашем API) отправляет уведомление толкателя, чтобы выгрузить / уничтожить еще несколько объектов.

В производственных сборках повторный рендеринг не является проблемой, поскольку мы просто уничтожаем объект, а затем все равно уходим (так что весь маршрут разрушается). Однако утверждение о сборках для разработчиков довольно разочаровывает, поскольку для восстановления сайта требуется обновление. Я понимаю, почему мы получаем ошибку, но в данном случае это довольно сложный рефакторинг, чтобы избежать ее, и в любом случае это не имеет значения, поскольку весь маршрут уничтожается. Есть ли способ поймать / подавить / изменить это на предупреждение? Я попробовал попробовать / поймать, а также обработчик ошибок маршрута, но ни один из них не воспользовался им.

@ feanor07 отправка действия изнутри get, которое аннулирует свойство a, которое уже было отображено, является обратным потоком данных, до того, как привязки с циклом обнаружат и молча выберут прямое направление в качестве победителя, но это дорого обходится, если это происходит несколько вещей и возвращается к источнику.

В основном у вас есть циклическая зависимость, и вам нужно, чтобы данные передавались вниз, не отображайте ошибку до того, как вы запустите проверку. Вы можете проверить в родительском компоненте, который выдает модель и ошибки, чтобы отобразить форму внутри своего блока.

@ feanor07 Ember.run.scheduleOnce... не сработало, но добавление всего одного Ember.run.schedule("afterRender", () => { ... }); к свойству set сначала указано трассировкой стека, устранило множество сообщений об ошибках, которые появлялись каскадом после исходного.

@neilthawani, который может скрыть ошибку, но не обязательно устраняет проблему. Ошибка означает, что вы устанавливаете значение дважды, тогда как вам, вероятно, следует устанавливать его только один раз. Помещая один из set в schedule , вы просто откладываете второй набор, так что это происходит в другом цикле выполнения. Вы не исправили основную проблему рендеринга дважды, когда вам нужно рендерить только один раз, просто обманули Ember, заставив не знать, что есть проблема, потому что теперь рендеринг происходит в отдельных циклах выполнения.

@ elwayman02 Ой ой. Спасибо. В основном совсем упустил суть.

Изменить: после борьбы с этим я вставил еще несколько afterRenders чем мне было удобно. У нас есть обработчик click на одном из наших компонентов визуализации данных, который переключает всплывающую подсказку. Установка флага isDisplaying внутри Ember.run.schedule("afterRender", () => { ... }); позволила нам отладить реальную проблему, которая на самом деле была обратным отслеживанием в контроллере, вызывая как компонент визуализации данных, так и компонент всплывающей подсказки.

tl; dr: Я не держал его там (тоже однажды получил ошибку Maximum call stack size exceeded ), но его использование было полезно для отладки, пока не была обнаружена настоящая проблема.

PSA для всех, кто только что обновляется: улучшенная ошибка утверждения «обратный повторный рендеринг», упомянутая выше @GavinJoyce, фактически включена в Ember 2.11. Также было высказано предположение, что может быть полезным сразу перейти на 2.11.

Ребята, мне нужна помощь: эта ошибка появляется, когда я пытаюсь использовать свойство модели, которое "принадлежит" другому. Я создал пустой проект, и он по-прежнему показывает то же самое. Что я делаю неправильно?

Кроме того, на моем сервере я использую .Net Core с JSON API .Net Core (https://github.com/Research-Institute/json-api-dotnet-core) - следуя их инструкциям.

На этом этапе рендеринг пользовательского интерфейса прерывается, однако данные загружаются, и я вижу желаемые значения.

    // 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}}

и я получаю ошибку:
Ошибка утверждения: вы дважды изменили "model.profile.contactProfile"@model: profile :: ember543: 1> за один рендеринг. Он был отрисован в шаблоне: fuels-ember / internal / profile / template.hbs и модифицирован в шаблоне: fuels-ember / internal / profile / template.hbs . Это было ненадежным и медленным в Ember 1.x и больше не поддерживается. См. Https://github.com/emberjs/ember.js/issues/13948 для получения более подробной информации.

PS: Я попытался использовать метод Ember.computed, чтобы получить свойство, и, похоже, это сработало. Это обязательно?

Обновление: я также обнаружил, что данные загружаются внутри помощника {{#each}}, но не непосредственно в шаблоне.

@lbarsukov
Возможно, это связано с https://github.com/emberjs/data/issues/5023, где повторный рендеринг с обратным отслеживанием вызван отношениями в вашем ответе jsonapi с установленным свойством links .

Для меня это была проблема, которая началась после Ember Data 2.13.2. Попробуйте использовать ember-data: 2.13.2, чтобы увидеть, решит ли это вашу проблему.

@ daniel-de-wit Большое спасибо мастеру - это действительно работает. Теперь он делает то, что мне нужно, и я доволен этим.

@lbarsukov @ daniel-de-wit Мы выпустили новую версию данных ember, в которой исправлена ​​эта проблема.

@lbarsukov Я думаю, это связано с вашими определенными отношениями. Есть большая вероятность, что один (или несколько) из belongsTo должен быть hasMany .

Допустим, у вас есть две модели: вопрос и ответ. Если вы вернете 10 ответов на вопрос, но каждый сериализатор вопроса ссылается на свой ответ, вам _ нужно_ правильно определить отношения.

// 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'),
        ...
    });

Когда данные попадают в определение нескольких пар вопрос / ответ, ожидая отношения 1-1, где его нет, это означает, что вопрос был изменен в середине рендеринга.

Из первоначального поста были упомянуты некоторые хуки:

Это довольно крайний пример, но он иллюстрирует проблему. Помимо init, didInitAttrs, didReceiveAttrs, willInsertElement и willRender также выполняются синхронно во время процесса рендеринга. Кроме того, возврат с возвратом часто является проблемой, связанной с поведением свойств с двусторонней привязкой.

Почему хуки didInsertElement и didRender работают как чудо, но другие хуки не работают с ошибкой twice render ?

@BenjaminHorn @ Blackening999 @Dhaulagiri @DingoEatingFuzz @ Gaurav0 @GavinJoyce @Redsandro @TRMW @ Turbo87 @aklkv @alidcastano @backspace @bdiz @bgentry @bjornharrtell @bryanhickerson @buschtoens @caseklim @cbou @chancancode @danaoira @ Даниель-де-остряк @fivetanley @fotinakis @gabrielgrant @ghost @jakesjews @janmisek @joukevandermaas , это все еще проблема, возможно, нам следует закрыть, как вы думаете?

Я исправил все случаи ошибки в своем приложении.

Каждый раз, когда я сталкивался с этим, я мог переставить вещи, чтобы этого больше не происходило, поэтому я думаю, что это нормально, чтобы закрыть.

Да пожалуйста закрой

конец эпохи 😬

👍

Извините, что поднял старую проблему.

Скажем, например, я визуализирую

{{this.myBool}}

и ошибка Error: Assertion Failed: You modified "myBool" twice

Я могу исправить ошибку, изменив ее на:

{{if this.myBool true false}}

Точно так же, если привязка имени класса вызывает проблему

Я могу изменить:

classNameBindings: ['myBool']

к

classNameBindings: ['myBool:yes:no']

Если я могу заглушить это предупреждение, почему Эмбер не может справиться с этим за меня?

Вот демонстрационный код, который я использовал:

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

Ничто из этого не «решает» проблему. Либо вы перешли в рабочий режим, либо в коде подтверждения / обнаружения есть ошибки. В любом случае вам нужно исправить сторону, которая присваивает / устанавливает значение, а не сторону, которая его потребляет.

Ok. Спасибо. Я понимаю проблему обратного отслеживания, описанную в этом исходном сообщении, потому что в нем явно указано set

Но в моем демонстрационном тидле set насколько я могу судить, нет.

_Edit_ Это вышло неправильно, я хочу сказать, что set поступает из _subsequent_ части шаблона, как в примере

Хм, у меня в твиддле не появляется ошибка, в какой последовательности кликов мне делать?

Щелкните "Открыть", а затем щелкните "Закрыть". Но кнопка закрытия дочернего компонента, а не родительского.

Я вижу, проблема в том, что во время разборки focusOut вызывается для компонента, который вызывает set для уже обработанного свойства. Я не уверен на 100%, как компонент теряет фокус и семантику времени. Я почти уверен, что варианты, которые вы пробовали, просто сбивают с толку систему отслеживания и скрывают основную проблему. Отследим это в новом выпуске? Я не уверен, что это актуальная проблема, но давайте проведем расследование.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги