等待并停止执行代码,直到事件处理程序触发

时间:2018-02-16 18:01:54

标签: javascript event-listener

我的代码启动了一系列我可能不会改变的功能:

doFirstThing();
doSecondThing();
doThirdThing();
// more functions...

每个函数都会创建一个事件处理程序。我希望函数做的是等到事件处理程序触发,然后返回并让下一个函数执行。我不能让第一个函数的事件监听器本身执行doSecondThing()(第二个执行第三个,依此类推),因为每次执行的函数的顺序和数量都不同。

我能想到的唯一解决方案是事件监听器将类似eventFired的布尔值更改为true,而函数检查中存在无限的while循环并等待布尔值变为true。

例如,假设有一个函数newText(str)可以更改按钮的文本,然后等待单击按钮。完成后,函数最终返回。使用未知值执行此函数未知次数的代码会自动生成,并且每次都不同,例如:

newText('Fizz');
newText('Buzz');
// some random code
newText('Foo');
// more code
newText('Bar');

所以预期的行为是有一个带有文本“Fizz”的按钮。单击后,文本将变为“Buzz”,依此类推,直到单击“Bar”。在四个函数调用之间可能还有一些其他代码,所以我认为不可能只让第一个函数创建一个事件处理程序,当被触发时调用下一个函数,依此类推。

我认为这会耗费大量资源,我可以使用setTimeout()每秒检查一次,但我觉得有一种更好,更清洁,更有效的方法,我可以找不到。或者这是解决此类问题的唯一最佳方法吗?

2 个答案:

答案 0 :(得分:3)

您需要等待点击按钮。为此,您需要将click事件转换为 promise ,当用户单击该按钮时,该事件将解析:

const once = (selector, event) => new Promise( res => document.querySelector(selector).addEventListener(event, res));

const setText = (selector, text) => document.querySelector(selector).textContent = text;

现在很容易做你想做的事情:

(async function(){
  setText("#btn", "click me");
  await once("#btn", "click");
  setText("#btn", "again please");
  await once("#btn", "click");
  setText("#btn", "done!");
})();

答案 1 :(得分:0)

听起来你需要发送自定义事件。您可以通过触发将执行特定于该事件的代码的自定义事件来控制操作的顺序。在以下示例中,创建了“选项”事件。根据您的方案,当单击按钮时,可以使用逻辑来确定下一步要做什么(采取哪个选项)。确定后,只需调度自定义事件即可。没有下一次事件发射就什么都不会发生。

本质上,该操作绑定到自定义事件。调度事件的顺序决定了代码执行的顺序。

下面的示例代码(无法演示,因为在线工具不支持自定义事件):

//Starting button
var buttonLabel = 'Fizz';
var currentOption = '';
// options represent the various "next steps" to take
var options = ['option1','option2','option3','option4','option5',];
var events = [];
options.forEach(o=>{
   var event = document.createEvent(o);
   events.push(event);
});
console.log(events);

function newText(){
  document.querySelector('button').textContent = buttonLabel;
}

function buttonClick(){
  switch (buttonLabel){
    case 'Fizz' :
      buttonLabel = 'Buzz';
      break;
    case 'Buzz' :
      buttonLabel = 'Foo';
      break;
    case 'Foo' :
      buttonLabel = 'Bar';
      break;
    case 'Bar' :
      buttonLabel = 'FooBar';
      break;
    case 'FooBar' :
      buttonLabel = 'Fizz';
      break;
    default :
      buttonLabel = 'What?';
      break;
  }
  currentOption = options[Math.random(0, options.length)];
  document.dispatchEvent(Math.random(0, options.length));
}
// Capture the button click...
document.querySelector('button').addEventListener('click', buttonClick);
// This sets up the activities (randomized here but just for demo)
document.addEventListener('option1', ()=>{
   alert('Option 1: \n running newText()...')

   newText();
});
document.addEventListener('option2', ()=>{
   alert('Option 2: \n doing something else...')
});

document.addEventListener('option3', ()=>{
   alert('Option 3: \n running newText()...')
   newText();
});

document.addEventListener('option4', ()=>{
   alert('Option 4: \n doing something else...')
});

document.addEventListener('option5', ()=>{
   alert('Option 5: \n running newText()...')
   newText();
});