如何在一个函数被独立调用之前暂停一个函数的调用?

时间:2019-04-21 05:32:16

标签: javascript promise callback

下面有可用的代码,但是我觉得必须有一个更干净的解决方案,而且我认为promise或callback不能在我的情况下起作用。

我有一个主函数(foo),它会在x毫秒后独立调用自身(在我的实际代码中,它会重复执行此操作)。调用自身时,它将增加存储在对象中的值。

我有第二个函数(栏),有时会随机调用。但是,我希望(在某些情况下)能够暂停该函数的执行,直到下次再次调用主函数(foo)为止。

在下面的工作示例中,bar会在调用prop时存储bar的当前值,然后不断重复检查prop的值,直到值更改为止。当值不再==时,bar执行else中的代码。这是可行的,但并不干净,而且计时不如bar仅听prop进行更改(或调用foo并执行)时的准确性在那一刻。

我不认为promise或callback会起作用,因为它们通常在将第二个函数作为参数传递的情况下使用。就我而言,我的第二个职能是拥有另一项工作,并且已经在重复做自己的工作。我也不想再次执行第二个函数,只希望调用它允许一个函数完成自己的执行。

对于我的实际情况,使用延迟也不理想。

更多详细信息

我的实际程序通过随机触发音频文件播放来制作音乐。 bar()是一项功能,用于确定播放声音的所有方式/属性(持续时间,音量,淡入/淡出等)。

foo()是一个主函数,它确定程序所在歌曲的哪个部分。因此,每次调用foo()时,它都会递增程序/歌曲所处的阶段(即,1, 2、3、4),它还调用了许多函数,更新了属性,这些属性改变了允许get()函数播放声音的方式。

因此,该程序主要随机播放声音(例如不像在刚性节拍/小节上播放),在某些情况下,我希望能够在小节上播放它们。由于foo()是跟踪此时间的函数,因此我为get()添加了功能,以便当未在节拍上触发声音时,声音会延迟到指定的节拍发生并允许玩。我有该功能。

当声音被分配为落在已经过去的节拍上时,技巧就来了。在这些情况下,我需要暂停get()直到下一个小节为止(即,再次调用foo()时)。在正常的音乐情况下,时间(每分钟节拍数)将是固定的,因此我可以简单地进行数学运算并将其setTimeout设置为正确的时间。但是,我的程序有点不传统,每次调用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 个答案:

答案 0 :(得分:1)

这是回调和观察者模式的完美用例。

您的主进程应产生拍子事件,并触发等待它们的函数。

您可以使用用于消息总线的框架来帮助您解决此问题,或者甚至可以使用可以保证主过程中发生下一个节拍的函数,但是本地解决方案也可以使用。您所需要的只是一系列侦听器功能,bar将功能的节拍部分添加到该列表中,然后foo调用(并从该列表中删除)这些功能。

答案 1 :(得分:0)

您可以使用一个布尔值来决定是否应在每次执行foo()时调用nar(),并在需要运行该函数时让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');
};

答案 2 :(得分:0)

也可以使用Promises来解决,但我认为有更好的解决方案:
使用setterProxy

它如何工作?

  • 设置者:
    设置器可以定义伪属性,该伪属性不能有值,但是如果您尝试设置该属性的值,则会调用一个函数,并以新值作为参数。

语法:

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

  • 代理: 使用代理对象,您可以执行设置器之类的操作,但是:
    1. 代理可用于监视和控制对对象的任何操作(获取,设置,删除,函数调用,类构造等)
    2. 与设置器不同,代理监视对象的所有属性。

语法:

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

好,但是如果我不想每次都打电话给bar怎么办!

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