2012-04-14 2 views
0

Я настраиваю форму для поиска или создания новой городской записи в веб-приложении. Мне нужно текстовое поле для города, чтобы сделать следующее:Keypress с задержкой, как ограничить только одно выполнение вызова функции?

  1. После получения ввода текста покажите «счетчик», указывающий, что компьютер обрабатывает вход.
  2. После того, как пользователь прекратил печатать в течение 1 секунды, отправьте запрос ajax для проверки ввода.
  3. Ответьте на состояние (действительно ли вход действителен).

У меня это почти работает, но у меня есть одна серьезная проблема: сценарий задержки, который я написал, работает, но после того, как задержка закончилась, он запускает остальную часть функции один раз за каждую клавишу, которая произошла во время задержки. Я бы хотел, чтобы он работал только один раз. Вот код, я работаю с (бревенчатыми консолями событие будет заменено с другими вызовами функций позже):

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

Почему функция getCity в настоящее время выполняется один раз в KeyUp, и как я могу исправить это? Кроме того, честно говоря, я очень новичок в javascript, поэтому я был бы признателен за любые другие предложения о том, как улучшить этот код.

Спасибо!

+0

jfriend и dbaseman, спасибо за ответы. Поскольку вы оба дали практически тот же ответ, я выбрал dbaseman, так как он был на 1 минуту раньше и имел значительно меньше репутации. Упрек для обоих, так как они были полезны. Спасибо! – Andrew

ответ

1

Похоже, проблема здесь:

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

Таймер получает значение NULL, поэтому он никогда не очищается. Я предлагаю объявить таймер вверху, после инициализации, а затем установить его в null только после его очистки или после его запуска.

+0

Общий вопрос js newb, но если синтаксис похож на его перемещение и сохранить его внутри 'locationSelector'? Нужно ли устанавливать его в качестве ключа и ссылаться на него как на «locationSelector.timer» или ... я об этом совершенно неправильно? – Andrew

+0

Нет, просто «таймер» работает до тех пор, пока вы находитесь во вложенном блоке, как и вы. Выглядит хорошо. – McGarnagle

2

Для начала, объявление переменной для timer должно быть в области, которая длится от одного события ключа к следующему. Как бы то ни было, это локальная переменная, которая воссоздается с нуля на каждом ключевом событии, поэтому вы получаете сразу несколько таймеров.

Переместить это:

var timer = null; 

в глобальном масштабе или более высокий объем, который сохраняется от одного ключевого события к другому. Вы можете также определить переменный таймер как свойство выбора местоположения, если вы хотите:

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

Затем, вы можете обратиться к нему как locationSelector.timer. Я также предлагаю, чтобы, когда ваш таймер действительно срабатывает, вы должны установить locationSelector.timer = null, так как таймер больше не активен.

Возможно, вам нужно очистить статус 'loading' после запуска ajax.

И ваш таймер установлен на 2 секунды, но вы сказали, что хотите подождать 1 секунду, чтобы не печатать.

+0

Re 2 секунды, это опечатка с моей стороны, спасибо, что поймал ее! Я отредактировал, чтобы исправить. – Andrew

+0

@Andrew - FYI, я добавил еще один вариант моего ответа, который определяет 'timer' как свойство вашего объекта locationSelector. – jfriend00