Запустите Ember.run.later из запускаемого действия - PullRequest
0 голосов
/ 30 декабря 2018

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

openEditWindow() {
  this.set('someChangingValue', true);
},

Вот функция, которая реагирует на действие someChangingValue изменение.

someChangingValue: false,
  someTestFunction: observer('someChangingValue', function() {
  var test = this.get('someChangingValue');

  if(test === true){
    Ember.run.later((function() {
      this.functionThatIsRunningEachTwoSeconds();
    }), 2000);
  } else {
    console.log('this should not do anything');
  }
}),

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

Спасибо!

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Просто чтобы уточнить, что не так с вашим текущим кодом (и не обязательно рекламировать это как решение), вы должны изменить значение, чтобы наблюдатель срабатывал.Если вы установите значение true, а затем снова установите его на true, даже не установив false, Ember внутренне проигнорирует это и не вызовет наблюдателя.См. twiddle , чтобы увидеть рабочий пример с использованием наблюдателей.

Код

init(){
    this._super(...arguments);
    this.set('count', 0);
    this.set('execute', true);
    this.timer();
  },
timer: observer('execute', function(){
    //this code is called on set to false or true
    if(this.get('execute')){
      Ember.run.later((() => {
        this.functionThatIsRunningEachTwoSeconds();
        }), 2000);
      // THIS IS SUPER IMPORTANT, COMMENT THIS OUT AND YOU ONLY GET 1 ITERATION
      this.set('execute', false);
    }
  }),
functionThatIsRunningEachTwoSeconds(){
    let count = this.get('count');
    this.set('count', count + 1);
    this.set('execute', true);
}

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

Если вы обработали кнопку редактирования на маршруте, вы могли бы очень аккуратно отменить ее при изменении маршрута

functionThatIsRunningEachTwoSeconds: task(function * (id) {
    try {
      while (true) {
        yield timeout(2000);
        //work function
      }
    } finally {
      //if you wanted code after cancel
    }
}).cancelOn('deactivate').restartable()

Деактивировать соответствуетна конец деактивировать перехват маршрута / событие:

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

0 голосов
/ 02 января 2019

Ember.run.later запускает функцию только один раз.Это ясно сказано в документах

Кроме того, вы используете очень старую версию ember?Ember.run.later устарел, и вы должны использовать частичный импорт import { later } from '@ember/runloop'; вместо этого

Что касается вашей задачи, есть как минимум два способа

Использование дополнения ember-concurrency

Установите ember-concurrency и напишите в контроллер:

import { task, timeout } from 'ember-concurrency';

export default Controller.extend({
  infiniteTask: task(function* () {
    while(true) {
      this.functionThatIsRunningEachTwoSeconds();
      yield timeout(2000);
    }
  }).drop(),
});

Шаблон:

{{#if infiniteTask.isIdle}}
  <button onclick={{perform infiniteTask}}>Start</button>
{{else}}
  <button onclick={{cancel-all infiniteTask}}>Stop</button>
{{/if}}

Этот аддон полезен во многих ситуациях, читайте его документыпонять, почему вам это может понадобиться

Создание функции, которая будет рекурсивно вызывать себя

Это классический JS-подход для повторения некоторых действий, но в ванильном JS мы используем setTimeout вместо ember's later.

import { later, cancel } from '@ember/runloop';

export default Controller.extend({
  infiniteFuction() {
    this.functionThatIsRunningEachTwoSeconds();
    this.set('infiniteTimer', later(this, 'infiniteFuction', 2000));
  },
  startInfiniteFunction() {
    //clear timer as safety measure to prevent from starting few 
    //"infinite function loops" at the same time
    cancel(this.infiniteTimer);
    this.infiniteFuction();
  },
  stopInfiniteFunction() {
    cancel(this.infiniteTimer);
    this.set('infiniteTimer', undefined);
  }
});

Шаблон:

{{#unless infiniteTimer}}
  <button onclick={{action startInfiniteFunction}}>Start</button>
{{else}}
  <button onclick={{action stopInfiniteFunction}}>Stop</button>
{{/unless}} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...