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



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

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

每个功能都会创建事件处理程序。我希望该功能要做的是等到事件处理程序触发,然后才返回并让下一个函数执行。我无法单独执行第一个函数的事件侦听器执行doSecondThing()(第二个执行第三个等(,因为每次都将执行的函数的顺序和数量是不同的。

我能想到的唯一的解决方案让evert the everner侦听器将像 eventFired这样的布尔人更改为true,而在函数检查中循环并等待布尔人在循环中,有一个无限的问题。

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

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

因此,预期的行为是具有带有文字" Fizz"的按钮。单击后,文本将更改为"嗡嗡声",依此类推,直到" bar"。四个函数调用之间可能还有其他一些代码,因此我认为只能使第一个函数创建一个事件处理程序,该函数在触发下一个函数时,依此类推。

我相信这将成为资源密集型,我可以使用setTimeout()每秒进行几次检查,但是我觉得有一种更好,更干净,更有效的方法可以找到我找不到的。还是这是解决此类问题的唯一和最佳方法?

您需要等待要单击的按钮。为此,您需要将单击事件转换为 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!");
})();

听起来您需要派遣自定义事件。您可以通过触发将执行特定于该事件的代码的自定义事件来控制操作顺序。在以下示例中,创建了"选项"事件。考虑到您的方案,当按下按钮的单击时,可以使用逻辑来确定下一步要做什么(要采用哪个选项(。一旦确定,只需派遣自定义事件即可。没有下一个事件发射,就不会发生任何事情。

本质上,该操作与自定义事件绑定。派遣事件的订单决定执行代码的顺序。

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

//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();
});

最新更新