2016-01-22 3 views
2

В этом example (RandomGifPair) как обновление, соответствующее NewGif, действительно подключено для выполнения после того, как родительский компонент запускает RandomGif.update act model.left? Кажется, что RandomGif.update NewGif maybeUrl нужно вручную уволить. Чтобы быть немного более явным, RandomGifPair запускает действие Left Left и возвращает пару модели/эффекта, вручную вызывая функцию обновления RandomGif. Возвращенный эффект осуществляется через Effects.map Left fx, и переходит к функции getRandomGif в RandomGifElm Effects, сопоставленный с вложенным компонентом

getRandomGif : String -> Effects Action 
getRandomGif topic = 
    Http.get decodeUrl (randomUrl topic) 
    |> Task.toMaybe 
    |> Task.map NewGif 
    |> Effects.task 

, который, насколько я понимаю, будет продолжать стрелять действие NewGif, который, из-за эффектов. map, теперь также отмечен слева. Только часть картины я отсутствующая как это действие сохраняется в пределах RandomGif и действия, соответствующих случай NewGif этого обновления фактически обожженное:

update : Action -> Model -> (Model, Effects Action) 
update action model = 
    case action of 
    RequestMore -> 
     (model, getRandomGif model.topic) 

    NewGif maybeUrl -> 
     (Model model.topic (Maybe.withDefault model.gifUrl maybeUrl) 
     , Effects.none 
    ) 

когда Main.elm имеет только обновление функция от RandomGifPair и, таким образом, не имеет случая для NewGif.

Я уверен, что ответ кроется в конкретных деталях портов, Effects.map, forwardTo или Tasks, которые мне не хватает.

Для справки, here is an attempt to solve the problem in javascript, который содержит запись в верхней функции обновления для NewGif и вручную вызывает RandomGif.update внутри нее. Вероятно, это не лучший способ попытаться понять вяза ...

ответ

4

Все действия входят в вашу функцию обновления верхнего уровня. Невозможно охватить действия для функции дополнительного обновления - они всегда входят в верхнюю часть. Таким образом, большинство программ будут вручную маршрутизировать действия вплоть до более низких функций обновления. Вот что здесь происходит. Все действия должны идти в RandomGifPair.update, и эта функция выполняет следующие функции: a) вызывает вспомогательные функции и b) сохраняет результаты в нужном месте в состоянии. Это может быть удивительно громоздким.

Here's the specific point in RandomGifPair.update that does the routing.

Line 42 говорят: «О, это Left действия? Дай мне act, который находится внутри там. Теперь у вас есть желаемый NewGif или RequestMore хранящегося в act, и вы знаете, что он был связан для левого. Строка 44 вызывает более низкую функцию обновления, которая знает, как ее обрабатывать. В строке 46 хранится результат более низкой функции обновления в модели (путем воссоздания всей модели с новым левым и повторного использования старого права).

Все это затенено шаблоном вокруг Effects. Если вы можете понять, как происходит движение, сначала вернитесь и примените ту же логику к эффектам, я думаю это станет яснее.

+0

О, я мог бы получить его. Позвольте мне спросить об этом: так что Left on line 42 обрабатывает оба действия RequestMore _and_ NewGif индивидуально и вызывает более низкое обновление для обоих действий? Удивительно просто. Таким образом, RequestMore изначально запускается как левое действие, которое в конечном итоге запускает NewGif, и оба обрабатываются в левом случае, когда обновление является агностическим, если это имеет смысл. –

+0

Я собираюсь пойти, да, вот здесь. Очень просто, просто легко заблудиться в предполагаемой сложности архитектуры портов/эффектов. Спасибо, что пропустили меня через него. –

+0

Большой момент для меня заключался в том, что такие вещи, как «Левые», фактически являются функциями. Похоже, ты понял! –

0

Возможно, я немного опоздал на вечеринку, но эффекты могут быть легко отображены.

Возьмите следующим образом:

type alias ChildModel = { number : Int } 

type alias Model = { firstChild : ChildModel } 


type ChildMsg = One | Two | Three 

type Msg Nothing | ChildMsg1 ChildMsg 


childUpdate : ChildMsg -> ChildModel -> (ChildModel, Cmd ChildMsg) 
childUpdate msg model = 
    case msg of 
    One -> { model | number = model.number + 1 } 
    Two -> { model | number = model.number + 2 } 
    Three -> { model | number = model.number + 3 } 

update : Msg -> Model -> (Model, Msg) 
update msg model = 
    case msg of 
    Nothing -> (model, Cmd.none) 
    ChildMsg1 mesg -> -- heres where the update is mapped 
     let 
     (childModel, childMsg) = childUpdate mesg model.firstChild 
     in 
     ({ model | firstChild = childModel }, Cmd.map ChildMsg1 childMsg) 

Cmd.map карты верхнего уровня Msg к вложенной компоненте. Подумайте, что змея поедает собственный хвост.

Смежные вопросы