Реализовать задержку ввода в ScalaJS?

У меня есть поле ввода поиска в приложении ScalaJS, которое отправляет запросы на внутренний сервер, пока пользователь вводит название города. Однако мне нужно реализовать задержку, чтобы запрос не запускался до определенной задержки (скажем, 1000 мс). Без такой задержки есть шанс, что я верну ложные срабатывания при поиске (например, если пользователь хочет найти «париж», то будет ложное попадание на «пар» — небольшой город в Корнуолле. , Англия - при вводе третьего символа)

Я попытался переписать эквивалент JavaScript на Scala, но часть setTimeout, похоже, не работает.

import scala.scalajs.js.timers.{SetTimeoutHandle, clearTimeout, setTimeout}

private def delay = () => {
  // Set initial timeout to do nothing after 0 ms
  var handle: SetTimeoutHandle = setTimeout(0)(() => {})

  (fn: Function0[Unit], ms: Double) => {
    clearTimeout(handle)
    handle = setTimeout(ms)(fn)
  }
}

Затем я обрабатываю событие пользовательского ввода с помощью Akka Actor.

def receive = {
  /************************************************
   * Client event
   * The user has typed something into the search field
   */
  case evt: Event =>
    delay()(handleInput, 1000.0)
}

Где handleInput — функция с нулевым параметром, которая получает ввод пользователя, а затем отправляет запрос на серверную часть.

Выполняется анонимная внутренняя функция, которая очищает, а затем сбрасывает тайм-аут, но функция handleInput никогда не вызывается.

Спасибо

Крис В.


person Chris W    schedule 20.03.2018    source источник
comment
Я отредактировал исходный вопрос, чтобы показать, что я пробовал.   -  person Chris W    schedule 22.03.2018


Ответы (1)


Проблема в вашем коде заключается в том, что вы передаете функцию типа () => Unit функции setTimeout, но setTimeout принимает параметр по имени . Другими словами, аргумент setTimeout должен быть инструкцией, которая будет выполняться по истечении времени ожидания. Если вы дадите ему функцию, то по истечении времени ожидания значение этой функции будет вычислено, но функция не будет вызвана!

Это похоже на ошибочную попытку сделать

val result = fn // result is the *function* itself, but does not call it

вместо

val result = fn() // fn is called, result is what it returns

Вы можете исправить вызов setTimeout, заменив fn на fn(). Кроме того, в таких обстоятельствах обычно более идиоматично использовать {} вместо () для параметра setTimeout, что также дает визуальную подсказку, что это параметр по имени:

(fn: Function0[Unit], ms: Double) => {
  clearTimeout(handle)
  handle = setTimeout(ms) {
    fn()
  }
}

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

// Set initial timeout to do nothing after 0 ms
var handle: SetTimeoutHandle = setTimeout(0) {}
person sjrd    schedule 22.03.2018
comment
Отлично, это исправлено! Спасибо за ваше объяснение - person Chris W; 23.03.2018