首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何用Elixir创建周期计时器?

如何用Elixir创建周期计时器?
EN

Stack Overflow用户
提问于 2021-11-04 13:17:29
回答 1查看 145关注 0票数 0

我正在尝试用Elixir创建一个周期性的计时器,它将周期(毫秒)的长度作为参数,并在经过时间后执行一个函数。用户也应该有权取消计时器。如果传递的函数返回:cancel值,那么它也应该取消计时器。下面是我的代码:

代码语言:javascript
代码运行次数:0
运行
复制
def start_timer(period, callback_function) do
    GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
    timer = Process.send_after(self(), :work, period)
    {:ok, %{timer: timer}}
  end
def handle_info(:work, period) do
    IO.puts("This should printed after every period")
    # Start the timer again
    timer = Process.send_after(self(), :work, period)

    {:noreply, %{timer: timer}}
  end

我还没有实现cancel-feature或参数函数的执行,因为上面的方法还不起作用。我该怎么做呢?任何建议都是非常感谢的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-04 16:43:34

看起来你没有在任何地方使用你的callback_function。如果你想让它在计时器的整个运行过程中都可用,你需要在第二个参数中将它传递给GenServer.start_link/3,例如

代码语言:javascript
代码运行次数:0
运行
复制
GenServer.start_link(__MODULE__, %{callback_function: callback_function}, name: __MODULE__)

下面是一些定期执行函数的代码:

代码语言:javascript
代码运行次数:0
运行
复制
defmodule Cronlike do
  use GenServer

  @allowed_units [:second, :minute, :hour, :day]

  def start_link(state) do
    GenServer.start_link(__MODULE__, state)
  end

  @impl true
  def init(%{interval: interval, unit: unit} = state) when is_integer(interval) and interval > 0 and unit in  @allowed_units do
    # wait, bang:
    Process.send_after(self(), :tick, to_ms(interval, unit))
    # bang, wait:
    # send(self(), :tick, to_ms(interval, unit))

    {:ok, state}
  end

  @impl true
  def handle_info(:tick, %{interval: interval, unit: unit, 
    callback_function: callback_function} = state) do

    case callback_function.() do
      :cancel -> send(self(), :quit)
      _ -> nil
    end

    Process.send_after(self(), :tick, to_ms(interval, unit))
    {:noreply, state}
  end

  def handle_info(:quit, state) do
    {:stop, :normal, state}
  end

  defp to_ms(interval, :second), do: interval * 1000
  defp to_ms(interval, :minute), do: to_ms(interval, :second) * 60
  defp to_ms(interval, :hour), do: to_ms(interval, :minute) * 60
  defp to_ms(interval, :day), do: to_ms(interval, :hour) * 24
end

这篇文章改编自我在Wait, Bang vs. Bang, Wait: Subtleties in Elixir Cron Scripts写的一篇相关文章

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69839878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档