Javascript事件处理和流量控制

时间:2009-08-21 15:06:13

标签: javascript loops events event-handling

我正在尝试构建一个根据提供的输入加载的网页。基本上,我在javascript中处理事件处理时遇到了一些麻烦。来自python,如果我想在继续显示下一个对象之前等待特定的键盘输入,我会创建一个 while 循环并在其中放置一个键侦听器。

的Python:

def getInput():
  while 1:
    for event in pygame.event.get(): #returns a list of events from the keyboard/mouse
      if event.type == KEYDOWN:
        if event.key == "enter": # for example
          do function()
          return
        elif event.key == "up":
          do function2()
          continue
        else: continue # for clarity

在尝试找到一种在DOM / javascript中实现它的方法时,我似乎只是崩溃页面(我假设由于While循环),但我认为这是因为我的事件处理写得不好。另外,使用“element.onkeydown = function;”注册事件处理程序我很难把头包起来,而setInterval(foo(),interval]并没有给我带来太大的成功。

基本上,我想要一个“监听”循环来为键X做一个特定的行为,但是当键Y被击中时要中断。

7 个答案:

答案 0 :(得分:8)

在JavaScript中,您放弃了对主循环的控制。浏览器运行主循环,并在发生事件或超时/间隔时回调到代码中。您必须处理该事件然后返回,以便浏览器可以继续执行其他操作,触发事件等。

所以你不能有'听'循环。浏览器会为您执行此操作,为您提供事件并让您处理它,但是一旦您完成事件处理,您必须返回。你不能回到不同的循环。这意味着您无法编写逐步的过程代码;如果你的状态在事件调用之间持续存在,你必须存储它,例如。在变量中。

这种方法不起作用:

<input type="text" readonly="readonly" value="" id="status" />

var s= document.getElementById('status');
s.value= 'Press A now';
while (true) {
    var e= eventLoop.nextKeyEvent(); // THERE IS NO SUCH THING AS THIS
    if (e.which=='a')
        break
}
s.value= 'Press Y or N';
while (true) {
    var e= eventLoop.nextKeyEvent();
    if (e.which=='y') ...

必须逐步调整分步代码,以便浏览器向您调用,而不是调用浏览器:

var state= 0;
function keypressed(event) {
    var key= String.fromCharCode(event? event.which : window.event.keyCode); // IE compatibility
    switch (state) {
        case 0:
            if (key=='a') {
                s.value= 'Press Y or N';
                state++;
            }
            break;
        case 1:
            if (key=='y') ...
            break;
    }
}

s.value= 'Press A now';
document.onkeypress= keypressed;

您还可以使用嵌套的匿名函数使代码看起来更加线性并清理一些状态:

s.value= 'Press A now';
document.onkeypress= function(event) {
    var key= String.fromCharCode(event? event.which : window.event.keyCode);
    if (key=='a') {
        s.value= 'Press Y or N';
        document.onkeypress= function(event) {
            var key= String.fromCharCode(event? event.which : window.event.keyCode);
            if (key=='y') ...
        };
    }
};

答案 1 :(得分:1)

你不应该在javascript中使用这样的循环。基本上你不想阻止浏览器完成它的工作。因此,您处理事件(onkeyup / down)。

也可以使用setTimeout而不是循环,如果你想等一下,如果发生了什么就继续

你可以这样做:

<html>
<script>
var dataToLoad = new Array('data1', 'data2', 'data3' );
var pos = 0;
function continueData(ev) {
  // do whatever checks you need about key
  var ele = document.getElementById("mydata");
  if (pos < dataToLoad.length)
  {
     ele.appendChild(document.createTextNode(dataToLoad[pos]));
     pos++;
  }
}
</script>
<body onkeyup="continueData()"><div id="mydata"></div></body></html>

每次释放一个密钥时,都会附加下一个数据字段

答案 2 :(得分:1)

为了更容易实现事件处理,我建议您使用PrototypeJquery等库(请注意,这两个链接都会将您带到各自的事件处理文档。

为了使用它们,你必须记住三件事:

  • 您要观察的DOM元素
  • 您要捕获的活动
  • 事件将触发什么操作

这三点是相互包容的,这意味着你在编写代码时需要注意3。

考虑到这一点,使用Prototype,你可以这样做:

Event.observe($('id_of_the_element_to_observe'), 'keypress', function(ev) {
  // the argument ev is the event object that has some useful information such
  // as which keycode was pressed.
  code_to_run;
});

以下是一个更有用的示例的代码,一个CharacterCounter(例如在Twitter中找到的那个,但肯定不太可靠;)):

var CharacterCounter = Class.create({

  initialize: function(input, counter, max_chars) {
    this.input = input;
    this.counter = counter;
    this.max_chars = max_chars;
    Event.observe(this.input, 'keypress', this.keyPressHandler.bind(this));
    Event.observe(this.input, 'keyup', this.keyUpHandler.bind(this));
  },

  keyUpHandler: function() {
    words_left = this.max_chars - $F(this.input).length;
    this.counter.innerHTML = words_left;
  },

  keyPressHandler: function(e) {
    words_left = this.max_chars - $F(this.input).length;
    if (words_left <= 0 && this.allowedChars(e.keyCode)) {
      e.stop();
    }
  },

  allowedChars: function(keycode) {
    // 8: backspace, 37-40: arrow keys, 46: delete
    allowed_keycodes = [ 8, 37, 38, 39, 40, 46 ];
    if (allowed_keycodes.include(keycode)) {
      return false;
    }
    return true
  }

});

答案 3 :(得分:0)

任何好的浏览器在遇到运行时间过长的脚本时都会崩溃。这是为了防止恶意网站锁定客户端应用程序。

你不能在javascript中拥有无限循环。相反,将一个事件监听器附加到窗口并指向处理程序中的处理(将其视为中断而不是轮询)。

示例:

function addEventSimple(obj,evt,fn) {
    if (obj.addEventListener)
        obj.addEventListener(evt,fn,false);
    else if (obj.attachEvent)
        obj.attachEvent('on'+evt,fn);
} // method pulled from quirksmode.org for cross-browser compatibility

addEventSimple(window, "keydown", function(e) {
    // check keys
});

答案 4 :(得分:0)

document.onkeydown = function(e) {
  //do what you need to do
}

这就是javascript所需要的一切。你不需要循环来等待事件发生,每当事件发生时将调用该函数,反过来可以调用其他函数,做任何需要做的事情。可以把它想象成那样,而不是你必须等待你想要发生的事件,你寻找的事件会在发生时让你知道。

答案 5 :(得分:0)

您可以将事件监听器附加到窗口对象,如此

window.captureEvents(Event.KEYPRESS);
window.onkeypress = output;
function output(event) {
  alert("you pressed" + event.which);
}

答案 6 :(得分:0)

查看YUI密钥监听器

http://developer.yahoo.com/yui/docs/YAHOO.util.KeyListener.html

使用密钥监听器,YUI负责捕获任何事件。在javascript中,几乎永远不会有一个实例,你必须在while循环中等待一些事情发生。

如果您需要有关事件处理方式的示例,请查看这些页面。

http://developer.yahoo.com/yui/examples/event/eventsimple.html