账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    Erlang 初学者对 Actor 的困惑(有例子)
    98
    0

    初学 Erlang,对 actor 模型刚刚了解,写了一段代码,做爬虫使用:

    -module(http).
    -compile([export_all]).
    
    init() ->
      ssl:start(),
      inets:start(),
      register(m, spawn(fun() -> loop() end)),
      % loop(),
      register(fetch, spawn(fun() -> x() end)),
      ok.
    
    start() ->
      L1 = [114689,114688,114691,114690,114695,114694,114697,114699,114698,114701,114700,114702,114705,114707,114706,110127,110128,110131,110132,110135,110136,110138,110143,110145,110144,110146,110149,110151,110150,110154,110157,110156,110159,110158,110161,110163], % 以这些详情页 id 做例子
    
      lists:map(fun(Gid) ->
        io:format("~p ~n", [Gid]),
        fetch ! {go, Gid}
      end, L1),
    
      m ! done,
    
      done.
    
    main(_) ->
      init(),
      start().
    
    loop() ->
      io:fwrite("this is in loop!!"),
      receive
        {no_res, Gid} ->
          io:format("~p no res ! ~n", [Gid]),
          loop();
        {have_res, Gid} ->
          io:format("~p have res ! ~n", [Gid]),
          loop();
        done ->
          io:format("wowowow", [])
      end.
    
    x() ->
      receive
        {go, Gid} ->
          http_post(Gid);
        _ ->
          ready
      end.
    
    http_post(Gid) ->
      URL = "https://xxx.com", % 以这个 url 为例子
      Type = "application/json",
      ReqArr = ["[{\"id\": \"", integer_to_list(Gid), "\"}]"],
      ReqBody = string:join(ReqArr, ""),
    
      case httpc:request(post, {URL, [], Type, ReqBody}, [], []) of
        {ok, {_, _, ResBody}} ->
          if
            length(ResBody) =:= 0 ->
              io:format("Y: ~p ~n", [Gid]);
              m ! {no_res, Gid};
            true ->
              io:format("N: ~p ~n", [Gid])
              m ! {have_res, Gid}
          end;
        {error, Reason} ->
          io:format("error cause ~p~n", [Reason]);
        _ ->
          io:format("error cause ~n", [])
      end.

    现在的问题是,我执行以后立刻就执行到 start()done 了,主进程立马结束,有没有什么办法让主进程等待这些请求完成再结束呢?

    还有,我这样写总感觉不对,有没有什么办法改进呢?

    请指教。

    2
    打赏
    收藏
    点击回答
    您的回答被采纳后将获得:提问者悬赏的 10 元积分
        全部回答
    • 0
    • 九来正 普通会员 1楼

      Actor 是 Erlang 中的一种设计模式,用于处理多个独立的实体之间的交互。在这个模式中,每个实体都是一个单独的Actor,它们有自己的状态和行为,可以在特定的情况下发生变化。而当一个新的实体需要与现有的实体交互时,Actor 可以调用某个特殊的接口,来实现这种交互。

      对于初学者来说,可能遇到的困惑包括以下几个方面:

      1. Actor 的概念:Actor 是一个单独的实体,有自己的状态和行为。它可以在特定的情况下发生变化。这与普通的函数、模块等概念不同,后者通常是作为一个整体被使用的。

      2. Actor 的调用接口:Actor 的调用接口是一个特殊的接口,它允许一个 Actor 与其他实体交互。例如,一个 Actor 可以被另一个 Actor 用来调用一个函数,或者调用一个方法来改变自身的状态。

      3. Actor 的生命周期:Actor 的生命周期是由其他实体来控制的。一旦一个 Actor 的状态发生了变化,它就会被其他实体所控制,直到这个实体不再需要它。

      以下是一个简单的例子,展示了如何在 Erlang 中使用 Actor 来处理一些简单的交互:

      ```erlang -module(myservice).

      function剧场() -> [{<<"Play>>>, [Hello]}] = actor(MyService, [{<<"Play>>>, [Hello]}]).

      myservice := actor(Hello, [{<<"Play>>>, [Hello]}]).

      Hello -> ok. ```

      在这个例子中,MyService 是一个单独的 Actor,它有一个内部函数 剧场,该函数会调用 Hello,并在接收一个包含字符串的元组时返回。Hello 是一个单独的 Actor,它有一个内部函数 Hello,该函数会调用 Hello,并在接收一个包含字符串的元组时返回。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部