Как приостановить вызов одной функции, пока другая функция не будет вызвана независимо? - PullRequest
0 голосов
/ 21 апреля 2019

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

У меня есть одна основная функция (foo), которая самостоятельно вызывает себя через x миллисекунд (в моем реальном коде она делает это многократно). Когда он вызывает сам себя, он увеличивает значение, хранящееся в объекте.

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

В моем рабочем примере ниже, bar сохраняет текущее значение prop при вызове bar, а затем продолжает проверять значение prop несколько раз, пока значение не изменится. Когда значения больше не ==, bar выполняет код в else. Это работает, но не чисто, и время не так точно, как могло бы быть, если бы bar просто прослушал изменение prop (или foo, который будет вызван), и было выполнено в тот момент.

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

Использование задержки также не идеально для моего реального случая.

Подробнее

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

foo() - это основная функция, которая определяет, в какую часть песни входит программа. Поэтому каждый раз, когда вызывается foo(), она увеличивает, на какой стадии находится программа / песня (т. Е. 1, 2, 3, 4) и также вызывает ряд функций, обновляющих свойства, которые изменяют то, как функциям get() разрешено воспроизводить звуки.

Итак, программа в основном воспроизводит звуки случайным образом (например, не на жестких битах / тактах), и я хочу иметь возможность воспроизводить их на тактах в некоторых случаях. Поскольку foo() - это функция, которая отслеживает это время, я добавил функциональность к get(), так что когда звук не запускается при ударе, он задерживается до тех пор, пока не произойдет назначенный удар, и затем ему будет разрешено играть. У меня эта функциональность работает.

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

Итак, подведем итог: bar() (звук) вызывается с целым набором сохраненных параметров, определяющих, как будет воспроизводиться звук. И мне нужно bar() сделать паузу после того, как он был вызван, пока он не услышит / не увидит, что foo() был вызван снова, и только тогда он завершает свою работу по воспроизведению звука.

Вот мой рабочий пример.

const config = {
  object: {
    prop: 1
  },
};

(function foo() {
  setTimeout(function() {
    config.object.prop = 3;
    console.log('foo changed the value of config.object.prop');
  }, 4000);
})();

bar();

function bar() {

  var prop = config.object.prop;

  (function nar() {
    if (prop == config.object.prop) {
      console.log('sorry, still waiting for config.object.prop to change');
      setTimeout(function() {
        nar();
      }, 1000);
    } else {
      console.log('Executed only after config.object.prop changed!!!');
    }
  })();
}

Ответы [ 3 ]

1 голос
/ 21 апреля 2019

Это идеальный вариант использования для обратных вызовов и шаблона наблюдателя.

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

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

0 голосов
/ 21 апреля 2019

Это также можно решить с помощью Promises, но я думаю, что есть лучшие решения:
Используя setter с или Proxy!

Как это работает?

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

Синтаксис:

var obj={
  prop:1,
  set anotherProp(value){
    //Handle set:
    this.prop=value
  }
}
obj.anotherProp=5
obj.prop //5

В переводе на ваш случай:

const config = {
  object: {
    prop: 1,
    set setterProp(value){
      this.prop=value;
      bar()
    }
  },
};

(function foo() {
  setTimeout(function() {
    console.log('foo changed the value of config.object.prop');
    config.object.setterProp = 3;
  }, 4000);
})();

function bar() {
    console.log('Executed only after config.object.prop changed!!!');
}
  • Прокси-сервер: С объектами Proxy вы можете делать такие вещи, как сеттеры, но:
    1. Прокси может использоваться для мониторинга и контроля любых действий с объектом (получение, установка, удаление, вызов функции, создание класса и т. Д.)
    2. В отличие от сеттеров, Proxy контролирует все свойства объекта.

Синтаксис:

var obj={
  prop:1
}
var proxy=new Proxy(obj,{
  set:function(obj,prop,value){
    //Handle set:
    obj[prop]=value;
  }
})
proxy.prop=5
proxy.prop //5
obj.prop   //5

В переводе на ваш случай:

const config = {
  object: {
    prop: 1
  },
};
const proxy=new Proxy(config.object, {
  set: function(obj,prop,value){
    //Handle set:
    obj[prop]=value;
    if(prop==='prop'){bar()};
  }
});
(function foo() {
  setTimeout(function() {
    console.log('foo changed the value of config.object.prop');
    proxy.prop = 3;
  }, 4000);
})();

function bar(){
  console.log('Executed only after config.object.prop changed!!!');
}

Хорошо, но что, если я не хочу звонить в бар каждый раз!

const barList=[]
const config = {
  object: {
    prop: 1
  },
};
const proxy=new Proxy(config.object, {
  set: function(obj,prop,value){
    //Handle set:
    obj[prop]=value;
    if(prop==='prop'){
      barList.filter(x=>{
        bar(...x)
        return false
      })
    };
  }
});
(function foo() {
  setTimeout(function() {
    console.log('foo changed the value of config.object.prop');
    proxy.prop = 3;
  }, 4000);
})();
function callBar(...args){
  barList.push(args)
}
function bar(...argument){
  console.log('Executed only after config.object.prop changed!!!', ...argument);
}
callBar();
callBar('with','some','arguments');
0 голосов
/ 21 апреля 2019

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

let runNar = false;

(function foo() {
  setTimeout(function() {
	if (runNar === true) {
		nar();
		runNar = false;
	}
    console.log('foo changed the value of config.object.prop');
  }, 4000);
})();

bar();

function bar() {
	runNar = true;
};

function nar() {
	console.log('Excuted when foo() is called');
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...