0

我正在设置一个表单以在 Web 应用程序中查找或创建新的城市记录。我需要城市的文本字段来执行以下操作:

  1. 收到文本输入后,显示“微调器”,指示计算机正在处理输入。
  2. 在用户停止输入 1 秒后,发送 ajax 请求以检查输入。
  3. 响应状态(输入是否有效)。

我几乎可以正常工作,但是我有一个主要问题:我编写的延迟脚本有效,但是在延迟结束后,它会在延迟期间发生的每个 keyup 运行一次函数的其余部分。我希望它只运行一次。这是我正在使用的代码(控制台日志事件稍后将替换为其他函数调用):

$(function() {
  locationSelector.initialize();
});

var locationSelector = {

  initialize: function() {
    locationSelector.bindCityName $('input#city_name')
  },

  city: {
    status: function( status ) {
      console.log( "Status message: " + status );
    },
    error: function(message) {
      console.log("Error message: " + message );
    }
  },

  bindCityName: function(selector) {
    selector.on('keyup', function() {
      locationSelector.city.status('loading');
      var timer = null;
      if(timer) {
        window.clearTimeout(timer);
      }
      timer = window.setTimeout(
        function() { locationSelector.getCity( selector ); },
        1000
      );
    });
  },

  getCity: function(selector) {
    if( selector.val() == "" ) {
      locationSelector.city.error('Cannot be blank.');
    } else {
      console.log("AJAX REQUEST");
    }
  }
};

Why is the getCity function is being run once per keyup, and how can I fix that? Also, to be honest I'm very much a javascript novice, so I would appreciate any other suggestions on how to improve this code scaffold.

Thanks!

4

2 回答 2

2

For starters, the variable declaration for timer needs to be in a scope that lasts from one key event to the next. As it is, it is a local variable that gets recreated from scratch on every key event so you're getting multiple timers going at once.

Move this:

var timer = null;

to the global scope or a higher scope that persists from one key event to the next. You can also define the timer variable as a property of location selector if you want:

var locationSelector = {
// other properties defined here
    timer: null
}

Then, you can refer to it as locationSelector.timer. I'd also suggest that when your timer actually fires that you should set locationSelector.timer = null since a timer is no longer active.

It also looks like you'll need to clear the 'loading' status once you run the ajax.

And, your timer is set for 2 seconds, but you said you want to wait 1 second for no typing.

于 2012-04-14T23:50:26.987 回答
1

It looks like the problem is here:

var timer = null;  
if(timer) {
    window.clearTimeout(timer);
}

Timer gets set to null, so it never gets cleared. I'd suggest declaring timer at the top, above initialize, and then setting it to null only after you clear it, or after it gets executed.

于 2012-04-14T23:51:21.200 回答