【问题标题】:How do I use handle_cast and handle_call in Erlang gen_server?如何在 Erlang gen_server 中使用 handle_cast 和 handle_call?
【发布时间】:2016-08-15 15:05:22
【问题描述】:

据我了解,我应该将handle_cast 用于异步请求,通过发送消息,然后在客户端通过receive..end 响应响应。

这是一个例子:

Pid ! {auth_user, {User, Password}}.

对于同步请求,当我想等待gen_server 发送响应时,我必须从模块中显式调用相应的函数,如下所示:

{ok, Result} = auth_server:auth_user({User, Password}).

上面的陈述是否正确?

如果后者是正确的,如果我已经有一个导出函数auth_user,为什么还需要这样的构造?

handle_call({authenticate_user, {Login, Password}}, _From, _) ->
    {reply, {}, {}}.

【问题讨论】:

  • 如果你通过Pid ! {auth_user, {User, Password}}.发送消息,它会触发回调Mod:handle_info({auth_user, {User, Password}}, State)
  • 除了 dogberts 回答:不幸的是,你必须在 erlang 中学习两个概念,一个是你自己编写 receive..end 循环的语言本身,然后是隐藏这个低级的 OTP 样式来自您的级别层并引入了不同的编程模型(回调),但值得使用,因为它处理了很多边缘情况。

标签: erlang


【解决方案1】:

您不会通过像这样直接发送消息来与gen_server 互动。您应该像这样使用gen_server:callgen_server:cast

Response = gen_server:call(Pid, {auth_user, {User, Password}})

call / cast 将处理将消息发送到Pid(并接收call 的响应)本身,以及许多边缘情况,例如在响应您的请求之前进程崩溃等。

如果后者是正确的,如果我已经有一个导出函数auth_user,为什么还需要这样的构造?

gen_server 在您希望在多个调用之间保持某些状态存储时很有用。例如,如果你想在内存中保存一个应用程序浏览量的全局计数器,你应该使用gen_server,将计数器存储为状态,并为它创建一个castcall每个请求。如果您没有要保留的状态,则应使用正常功能。

【讨论】:

  • AFAIK,在 Erlang 世界中,当工具已经存在时不使用 OTP 是一种不好的做法。或者至少,向新来者推荐它。我自己也是新手,所以把这个当作我的一个附带问题。
猜你喜欢
  • 2016-04-03
  • 2020-08-18
  • 2017-01-13
  • 2019-12-17
  • 2018-10-14
  • 2010-11-24
  • 2012-09-05
  • 2011-08-09
  • 2014-11-09
相关资源
最近更新 更多