2015-07-14 9 views
8

Was ist der beste Weg in Elixier, um einen Vordergrundprozess zu erstellen, der in jeder gegebenen Zeit ankreuzen?Wie erstelle ich einen Event-Emitter mit Elixier, der otp-Weg

Mein Hauptproblem ist, dass ein Ansatz wie:

defmoulde Ticker do 
    def tick do 
    do_something() 
    :timer.sleep(1000) 
    tick 
    end 
end 

Werke, sondern durch Design ist falsch. Es tippt definitiv nicht jede Sekunde, aber jede Sekunde PLUS die Zeit für do_something() zu vervollständigen. Ich könnte einen Prozess erstellen, um das "Etwas" zu behandeln, aber es gibt immer noch eine kleine Verzögerung.

Ich versuche auch, eine Mix-App zu bauen, es gibt einige GenServer beteiligt, und ein Haupt Vordergrundprozess (der ich hier frage), der die Server alle x Sekunden aufrufen sollte. Gibt es eine Möglichkeit, dies zu tun?

Antwort

13

Ich denke, timer:apply_interval/4 sollte Ihren Bedürfnissen entsprechen. Es ist so etwas wie dieses verwendet:

defmodule Tick do 
    def tick do 
    IO.inspect(:tick) 
    end 
end 

:timer.apply_interval(:timer.seconds(1), Tick, :tick, []) 

Die Argumente sind, um das Intervall, einen Modulnamen, um die Funktion aufzurufen und die Argumente zu nennen mit. Dann können Sie innerhalb dieser Funktion Nachrichten an Ihre GenServers senden. Lesen Sie die vollständige Dokumentation hier aus: apply_interval/4

Eine andere Sache zu prüfen ist, dass, wenn Ihre tick Funktion immer nur bis zu einem gewissen GenServers einfachen Botschaften zu senden, dann ist es wahrscheinlich extrem schnell, so dass Ihre Implementierung in Ordnung sein könnte, einmal eingewickelt in a Task und in den Überwachungsbaum eingesteckt (wenn Sie sich nicht um die mögliche leichte Drift kümmern).

+1

Ich interessiere mich für die mögliche Zeitdrift. Wie würde ich jede Zeitverschiebung vermeiden? –

+1

'apply_interval' sollte ziemlich anständig sein, aber die Dokumente geben nur an, dass" die Timeouts nicht genau sind, aber mindestens so lang sind wie angefordert ". –