首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >榆树分户订阅?

榆树分户订阅?
EN

Stack Overflow用户
提问于 2016-12-31 15:35:13
回答 2查看 207关注 0票数 2

我和Elm和WebRTC一起玩,所以我做了一个监听端口,接收来自js的一些消息:

代码语言:javascript
复制
type alias Message = 
    { channel : String
    , data : String
    }
port listen : (Message -> msg) -> Sub msg

现在,我希望能够将消息划分到我的应用程序的不同部分。例如,聊天使用“聊天”通道,而游戏逻辑使用“游戏”。

是否有可能创建一个listenTo String订阅来过滤具有正确通道的消息(只返回数据)?或者是另一种方式?

更新:

我现在拥有的是这样的东西:

在我的main.elm中,我有一个如下所示的更新。它可以接收消息(来自rtc)本身,并发送消息给它聊天。(我后来也添加了一个"ForGame“)

代码语言:javascript
复制
type Msg = Received WebRTC.Message | ForChat Chat.Msg

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        Received message -> 
            let 
                _ = Debug.log ("Received message on \"" ++ message.channel ++ "\": " ++ message.data)
            in
                ( model
                , Cmd.none
                )
        ForChat msg ->
            let 
                (chatModel, chatCmd) = Chat.update msg model.chat
            in  
                ({ model | chat = chatModel}, Cmd.map ForChat chatCmd)

然后,我有将所有订阅组合在一起的订阅:

代码语言:javascript
复制
subscriptions : Model -> Sub Msg
subscriptions model = 
    Sub.batch 
        [ WebRTC.listen Received
        , Sub.map ForChat <| Chat.subscriptions model.chat
        ]

在Chat.elm中,我有一个类似的结构,有一个处理它的消息的更新。聊天的订阅侦听来自WebRTC的所有消息,但只过滤那些有频道聊天的消息:

代码语言:javascript
复制
subscriptions : Model -> Sub Msg
subscriptions model = WebRTC.listen forChatMessages

forChatMessages : WebRTC.Message -> Msg
forChatMessages webrtcMessage =
    if webrtcMessage.channel == "chat"
    then
        let
            message = decodeMessage webrtcMessage.data
        in
            case message of
                Ok msg -> Receive msg
                Err error -> Debug.log ("Received unreadable message on chat channel \"" ++ toString webrtcMessage.data ++ "\" with error \"" ++ error ++ "\"") Ignore
    else
        Ignore

(忽略是用于聊天的Msg,它不做任何case msg of Ignore -> (model, Cmd.none)decodeMessage使用解码器来解码消息decodeMessage : String -> Result String Message。)

我对此非常满意,因为这样聊天的所有逻辑都在Chat.elm中。因此,main.elm不需要知道聊天使用的是什么频道。Chat只是遵循标准结构(Msg、更新、查看、订阅)和main转发所有内容。

唯一不太好的地方是,在Chat.elm中,我有forChatMessages函数。用于:subscriptions model = WebRTC.listen forChatMessages.我想让它更易于再利用,这样它就会变成这样:

代码语言:javascript
复制
subscriptions model = WebRTC.listen for "chat" decodeMessage Receive Ignore

然后,它将被游戏重用:

代码语言:javascript
复制
subscriptions model = WebRTC.listen for "game" decodeGameInfo UpdateInfo Ignore

更新2:

我设法将forChatMessages函数概括为:

代码语言:javascript
复制
for : String -> (String -> Result String d) -> (d -> msg) -> msg -> Message -> msg
for channel decoder good bad webrtcMessage =
    if 
        webrtcMessage.channel == channel
    then
        let
            decoded = decoder webrtcMessage.data
        in
            case decoded of
                Ok data -> good data
                Err error -> Debug.log ("Failed decoding message on " ++ channel ++ "channel \"" ++ toString webrtcMessage.data ++ "\" with error \"" ++ error ++ "\"") bad
    else
        bad

所以我想我自己找到了解决办法。除非有人对此有意见。也许有一种更清洁/更好/更好的方法来做同样的事情?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-06 13:16:44

我自己找到了一个解决方案,并把它添加到了原来的问题中。

为了清晰起见,这是一个简短的版本:

在我的main.elm:

代码语言:javascript
复制
type Msg = Received WebRTC.Message | ForChat Chat.Msg

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        Received message -> 
            let 
                _ = Debug.log ("Received message on \"" ++ message.channel ++ "\": " ++ message.data)
            in
                ( model
                , Cmd.none
                )
        ForChat msg ->
            let 
                (chatModel, chatCmd) = Chat.update msg model.chat
            in  
                ({ model | chat = chatModel}, Cmd.map ForChat chatCmd)


subscriptions : Model -> Sub Msg
subscriptions model = 
    Sub.batch 
        [ WebRTC.listen Received
        , Sub.map ForChat <| Chat.subscriptions model.chat
        ]

在Chat.elm中:

代码语言:javascript
复制
subscriptions : Model -> Sub Msg
subscriptions model = WebRTC.listen <| for "game" decodeGameInfo UpdateInfo Ignore

在WebRTC.elm中:

代码语言:javascript
复制
type alias Message = 
    { channel : String
    , data : String
    }
port listen : (Message -> msg) -> Sub msg

for : String -> (String -> Result String d) -> (d -> msg) -> msg -> Message -> msg
for channel decoder good bad webrtcMessage =
    if 
        webrtcMessage.channel == channel
    then
        let
            decoded = decoder webrtcMessage.data
        in
            case decoded of
                Ok data -> good data
                Err error -> Debug.log ("Failed decoding message on " ++ channel ++ "channel \"" ++ toString webrtcMessage.data ++ "\" with error \"" ++ error ++ "\"") bad
    else
        bad
票数 1
EN

Stack Overflow用户

发布于 2016-12-31 20:12:03

假设您有以下Msg定义:

代码语言:javascript
复制
type Msg
    = Listen Message
    | GameChannel String
    | ChatChannel String

然后,update函数可以对channel值进行操作,并使用正确的通道再次调用update,忽略除"game""chat"以外的所有channel值。

代码语言:javascript
复制
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Listen message ->
            case message.channel of
                "game" ->
                    update (GameChannel message.data) model

                "chat" ->
                    update (ChatChannel message.data) model

                _ ->
                    model ! []

        GameChannel data ->
            ...

        ChatChannel data ->
            ...

您的订阅功能如下所示:

代码语言:javascript
复制
subscriptions : Model -> Sub Msg
subscriptions model =
    listen Listen
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41409662

复制
相关文章

相似问题

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