2015-06-21 2 views
2

Как я могу сделать два независимых действия внутри одной функции в Elm? Есть ли какой-либо шаблон или явная функция?Как сделать два независимых действия внутри одной функции?

Вообще говоря, я не уверен, как реализовать загрузку данных ajax внутри Elm Architecture.

Например, я хотел бы сделать Http.get и вернуть модифицированную функцию аргумент, как этот

fetchCustomers model = 
    Http.get parseCustomers "/customers" `andThen` setCustomers 
    { model | fetchingCustomers <- True } 

ответ

2

TL; DR

Вы делаете так, возвращая как в кортеже. Затем вы разделите сигнал с вашего обновления на foldp, поместите часть модели в функцию просмотра и поместите задачи в порт для выполнения. Об этом говорится в сообщении архитектуры в конце под заголовком Один последний шаблон.

Более длинный ответ

Поскольку вы ссылка на Эой архитектуру, дай мне ссылку на это тоже, но, в частности, последняя часть: One Last Pattern.

Что вы хотите сделать здесь, является частью «обновления» вашей программы, где вы не только обновляете свою модель, но и делаете что-то еще на стороне. Таким образом, вы не только вернуть новую модель, но и дополнительная вещь, которую вы хотите сделать (в этом случае запрос HTTP):

fetchCustomers model = 
    ({ model | fetchingCustomers <- True } 
    , Http.get parseCustomers "/customers" `andThen` setCustomers 
) 

Вместо использования StartApp как страницы архитектуры делает, вы можете вставить в start function из упаковки. Теперь у вас есть доступ к почтовому ящику, в котором происходят действия, поэтому вы можете передать его вашему обновлению, чтобы вы могли отправить свои результаты Http. И вы можете разделить кортеж, который вы возвращающийся из функции обновления для фактического выполнения задачи:

start app = 
    let 
    actions = 
     Signal.mailbox Nothing 

    address = 
     Signal.forwardTo actions.address Just 

    model = 
     Signal.foldp 
     (\(Just action) (model,_) -> app.update actions action model) 
     -- ignore task:^ ^^^    ^^^^^^^^:add mailbox 
     app.model 
     actions.signal 
    in 
    (Signal.map (fst >> app.view address) model, Signal.map snd model) 
--^   ^^^^^^^  :split model:  ^^^^^^^^^^^^^^^^^^^^^^^ 


fetchCustomers actions model = 
    ({ model | fetchingCustomers <- True } 
    , Http.get parseCustomers "/customers" 
    `andThen` (SetCustomers >> Signal.send actions.address) 
    -- use mailbox to send Http results as an input action again 
) 

-- larger update function you probably have 
update actions action model = case action of 
    -- ... 
    SetCustomers cust -> setCustomers cust 
    -- ... 
    -- fetchCustomers actions model 

(output, tasks) = start { model: model, view: view, update: update } 

-- task execution: 
port httpGets = tasks 

-- output your view 
main = output 

Вы можете найти более examples делать Http на сайте в разделе «задач».

+0

Это отличный ответ! Большое спасибо! Не могли бы вы объяснить свой код немного больше: вы возвращаете кортеж из 'app'. Я не вижу, что вы используете этот кортеж в любом месте? Это делается для того, чтобы принудительно оценить элемент второго кортежа? – nidu

+0

@nidu: Вы имеете в виду кортеж, который я возвращаю из 'start'? Это используется в строке '(output, tasks) = start {model: model, view: view, update: update}'. – Apanatshka

+0

Можете ли вы уточнить подпись функции «обновления»? Должен ли он вернуть модель или кортеж? – phtrivier

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