LitElement render() не вызывается при быстром обновлении состояния

У меня возникла проблема с обновлением изображений на полимерной странице. Мой элемент выглядит следующим образом:

import { html, LitElement, property } from 'lit-element';
import { connect } from 'pwa-helpers/connect-mixin.js';

// These are the shared styles needed by this element.
import { SharedStyles } from '../../styles/shared-styles.js';

// This element is connected to the Redux store.
import { store, RootState } from '../../store.js';

class TFJSItem extends connect(store)(LitElement) {
  @property({type: Number})
  private _prediction = 0;

  static styles = SharedStyles;

  protected render() {
    console.info(this._prediction);
    return html`
      <section>
        <h2>TFJS</h2>
        <p>${this._prediction}</p>
      </section>
    `;
  }

  // This is called every time something is updated in the store.
  stateChanged(state: RootState) {
    console.info(state.network!.prediction);
    this._prediction = state.network!.prediction;
  }
}

window.customElements.define('tfjs-item', TFJSItem);

У меня есть скрипт, работающий на 1000 итераций, который отправляет действие в редукс для обновления числа, хранящегося в network.prediction. Однако число, отображаемое в элементах, обновляется только один раз, после последнего изменения состояния. Однако, поскольку я хочу, чтобы это был номер, работающий в реальном времени, я хочу, чтобы каждое изменение записывалось. Странно то, что второй console.info() выполняется для каждого изменения, однако рендер вызывается только один раз.

Данные поступают из процесса обучения tfjs. Я хочу обновлять прогноз каждый раз, когда делается новая итерация:

import * as tf from '@tensorflow/tfjs';
import * as d from './data';
import * as m from './model';

import { store } from '../store.js';
import { newPrediction } from '../actions/network.js';

export class Training {
  model: m.Model;
  data: d.Data;
  iterations: number;

  constructor(model: m.Model, data: d.Data) {
    this.model = model;
    this.model.model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});
    this.data = data;
    this.iterations = 0;
  }

  start() {
    var this_ = this;
    if (this.iterations < 1000) {
      this.iterate();
    }
  }

  iterate() {
    this.iterations++;
    tf.tidy(() => {
      const prediction = this.model.model.predict(tf.tensor2d([5], [1, 1]) as tf.Tensor) as tf.Tensor<tf.Rank>;
      store.dispatch(newPrediction(prediction));
      this.model.model.trainOnBatch(this.data.xs, this.data.ys);
    });
  }
}

вы ждете некоторое время (setTimeout или эквивалент) между отправкой каждого действия в избыточность? я знаю, что Redux может пакетно обновлять состояние, поэтому вы можете увидеть последнее, только если они слишком близко друг к другу

Tom Cumming 01.03.2019 16:58

Спасибо вам за эту информацию! Теперь я жду 1 мс после каждой итерации следующим образом: start() { var this_ = this; if (this.iterations < 1000) { this.iterate(); setTimeout (function() { this_.start(); }, 1); } }

SparkierFlunky 05.03.2019 17:18

Вы хотите опубликовать это как ответ? Тогда я могу отметить это как правильное.

SparkierFlunky 05.03.2019 17:21

Еще одна возможная проблема: ваш тренер TFJS должен периодически вызывать await tf.nextFrame(), чтобы передать управление, чтобы избежать зависания пользовательского интерфейса. Обычно это происходит автоматически при использовании LayersModel.fit() и LayersModel.fitDataset(), но проверьте аргумент yieldEvery, чтобы настроить поведение (js.tensorflow.org/api/latest/#tf.LayersModel.fit).

David Soergel 06.03.2019 22:24

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

SparkierFlunky 07.03.2019 08:35
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
2
5
1 573
1

Ответы 1

LitElement пакетно вызывает render() (фактически весь конвейер обновлений). Ожидается, что если вы много обновляете состояние в одной задаче, будет только один вызов render().

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

Другие вопросы по теме