Elm:迭代列表执行多个 HTTP 请求

Elm: Iterate list performing multiple HTTP requests

我想知道是否可以在迭代组列表方面获得一些帮助,为每个组发出 POST 请求以创建 'room',为每个组迭代用户并制作POST 请求将他们分配到这个特定的房间。

我有以下型号。

model = {
  groups = [
    {
      title = "Foo"
      , users = [
        { name = "Joe" }
        , { name = "Mary" }
      ]
    },
    {
      title = "Bar"
      , users = [
        { name = "Jill" }
        , { name = "Jack" }
      ]
    }
  ]
}

期望的结果是创建了房间 Foo 并分配了 Joe 和 Mary,创建了 Bar 并分配了 Jill 和 Jack。

目前,该视图只是一个触发操作的简单按钮。

div []
  [ button [ onClick InviteUsersToRoom ] [ text "Invite users to room" ] ]

我创建了 2 个 POST 请求:

  1. createRoom: 使用 title 创建一个房间,使用 title 和 return room_id

  2. addUser:取一个room_id和一个用户的name,将用户添加到房间,然后return ok

  3. 的状态

示例:

-- create a room for each group
-- passing in `title` as the room name
-- which will return the room id from `decodeCreateRoomResponse`

createRoom : String -> String -> Cmd Msg
createRoom title =
  Task.perform
    CreateRoomsFail
    CreateRoomsSuccess
    (Http.post
      decodeCreateRoomResponse
      ("https://some_api?room=" ++ title)
      Http.empty
    )


decodeCreateRoomResponse : Json.Decoder String
decodeCreateRoomResponse =
  Json.at ["room", "id"] Json.string


-- add a user to a room using a `room_id` and the user's name
-- returns a bool from `decodeAddUserResponse`

addUser : String -> String -> Cmd Msg
addUser room_id user =
  Task.perform
    AddUserFail
    AddUserSuccess
    (Http.post
      decodeCreateChannelResponse
      ("https://some_api?room=" ++ room_id ++ "&user=" ++ user)
      Http.empty
    )


decodeAddUserResponse : Json.Decoder String
decodeAddUserResponse =
  Json.at ["ok"] Json.bool

我想知道你将如何把它拼接起来,以便点击:

  1. 迭代每个组
  2. 创建 POST 创建房间
  3. 从响应中获取 room_id 并迭代用户
  4. POST room_id 和用户名

感谢任何帮助。

您有一些分散的错误,我不会明确指出这些错误,因为编译器会帮助您,但您已经有了一个良好的开端。您已经建立了一些 Http 处理 Cmd,因此您只需要使用 update 函数连接起来。

让我们明确定义您的模型(您可能已经在这样做,但它不在您的示例中):

type alias User =
  { name : String }

type alias Group =
  { title : String
  , users : List User
  }

type alias Model =
  { groups : List Group }

根据您的功能,以下是我解释您的 Msg 类型的方式,其中一个小改动是将用户列表作为参数添加到 CreateRoomsSuccess

type Msg
  = InviteUsersToRoom
  | CreateRoomsFail Http.Error
  | CreateRoomsSuccess (List User) String
  | AddUserFail Http.Error
  | AddUserSuccess Bool

现在我们可以调整 createRoom 以传递要创建的用户列表。请注意,此时不会创建任何用户。它使用柯里化创建一个部分应用的函数,这样当 CreateRoomsSuccess 案例在 update 函数中处理时,它已经有了需要创建的用户列表(而不是必须查看他们在 model 列表中):

createRoom : Group -> Cmd Msg
createRoom group =
  Task.perform
    CreateRoomsFail
    (CreateRoomsSuccess group.users)
    (Http.post
      decodeCreateRoomResponse
      ("https://some_api?room=" ++ group.title)
      Http.empty
    )

要创建房间列表,您只需将组列表映射到执行 post 的 Cmd 列表。单击按钮时会发生这种情况:

case action of
  InviteUsersToRoom ->
    model ! List.map createRoom model.groups
    ...

您必须在发生错误时实施更新案例。接下来,我们必须处理 CreateRoomsSuccess 消息。这是您需要查找组的用户列表的地方。同样,您将映射您已经创建的处理 Http 任务的函数:

case action of
  ...
  CreateRoomsSuccess users roomID ->
    model ! List.map (addUser roomID << .name) users
  ...

您必须处理 AddUserFailAddUserSuccess 情况,但上述示例应该可以帮助您了解如何 post 多条消息并根据成功或每个都失败。