Erlang 初学者对 Actor 的困惑(有例子)

发布于 2022-09-12 00:12:40 字数 1869 浏览 23 评论 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 了,主进程立马结束,有没有什么办法让主进程等待这些请求完成再结束呢?

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

请指教。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

何以畏孤独 2022-09-19 00:12:40

就本例而言:

start() ->
  L1 = [114689,1146881,110158,110161,110163],

  lists:map(fun(Gid) ->
    io:format("~p ~n", [Gid]),
    fetch ! {self(),go, Gid} %% 这里发的时候带上自己的pid,worker的工作完成后通知主进程
  end, L1),
  m ! done,
  wait(length(L1)), %% 等待任务完成
  done.
  
wait(0)->ok;
wait(N)->
    receive
        _->
            wait(N-1)
    end.

改进的写法:
看看gen_server的用法。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文