2016-09-22 1 views
1

У меня сценарий:Как реализовать debounced autosave в Elm lang 0.17?

Когда пользователь перестает печатать в текстовой области, я хочу подождать 2 секунды, и если пользователь не изменит ничего в текстовом поле за эти 2 секунды, я хочу сохранить содержимое текстового поля на сервере. Если пользователь меняет что-то в текстовом поле за эти 2 секунды, я хочу перезапустить тайм-аут ожидания.

В JavaScript, я бы реализовать что-то вроде этого

http://codepen.io/ondrejsevcik/pen/LRxWQP

// Html 
<textarea id="textarea"></textarea> 
<pre id="server"></pre> 

// JavaScript 
var textarea = document.querySelector('#textarea'); 

var textValue = ""; 
textarea.oninput = function (e) { 
    textValue = e.target.value; 
    setSaveTimeout(); 
} 

let saveTimeout; 
function setSaveTimeout() { 
    if (saveTimeout) { 
    clearTimeout(saveTimeout); 
    } 
    saveTimeout = setTimeout(saveToServer, 2000); 
} 

function saveToServer() { 
    document.querySelector('#server').innerText = 
    'Value saved to server: ' + textValue; 
} 
+1

[ 'Process.sleep'] (http://package.elm-lang.org/packages/elm-lang/core/4.0.5/Process#sleep) является' setTimeout' эквивалент в Элм , по всей видимости. Я смог найти [этот пример] (https://github.com/fredcy/example-elm-debounce/blob/master/Debounce.elm), используя его для дебюта, но независимо от того, является ли это лучшим способом, я Не уверен. –

+1

Кроме того, вот нить из группы, в которой обсуждается, как отменить: https://groups.google.com/forum/#!topic/elm-discuss/w4MwjIaTiIY –

ответ

0

Одним из способов достижения поведение является ..

  1. Hook onInput событие
  2. В onInput обработчик, создать задачу, которая fi res через 2 секунды, с текущим значением textarea. Также сохраните содержимое текстовой области.
  3. проверить, изменилось ли значение и сохранить его, если значение не изменилось.

Здесь он не отменяет Task, так что это может быть неэффективно.

-- MODEL 
type alias Model = 
    { str : String 
    , saved : String 
    } 

init : (Model, Cmd Msg) 
init = 
    (Model "" "", Cmd.none) 

-- UPDATE 
type Msg 
    = ChangeText String 
    | Save String 
    | NoOp() 

update : Msg -> Model -> (Model, Cmd Msg) 
update msg model = 
    case msg of 
    NoOp _ -> (model, Cmd.none) 
    Save str -> 
     let 
     _ = Debug.log "save" str 
     newmodel = 
      if model.str /= str 
      then model 
      else { model | saved = str } 
     in (newmodel, Cmd.none)  
    ChangeText str -> 
     let 
     _ = Debug.log "textarea" str 
     cmd = Task.perform NoOp Save <| 
      Process.sleep (2 * Time.second) 
      `Task.andThen` 
      \_ -> Task.succeed str 
     in ({ model | str = str }, cmd) 

-- VIEW 
view : Model -> Html Msg 
view model = 
    Html.div [] 
    [ Html.textarea [ onInput ChangeText ] [] 
    , Html.div [] [ Html.text <| "saved: " ++ model.saved ] 
    ]