SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Webアプリケーション開発技術の新潮流スタディーズ

関数型リアクティブプログラミング言語Elmに学ぶ フロントエンド開発の新しい形 【後編】

Webアプリケーション開発技術の新潮流スタディーズ 第5回


  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンロード samples.zip (8.2 KB)

Elm Architectureの応用 ⑵:非同期通信の導入

リッチなWebアプリケーションの構築に非同期通信は欠かせません。 Elm Architectureに非同期通信を組み込むにはどうすればよいでしょうか?

Taskの利用

ElmにはTaskという非同期処理を行うための仕組みが用意されています。

次の例は、非同期通信でテキストを取得する例です。 いくつか新しい文法が登場しますが、1つずつ見ていきますので焦る必要はありません。

import Http
import Json.Decode

port getData : Task Http.Error String
port getData = Http.getString "https://example.com/"

Http.getString関数はURLを渡すと、Task Http.Error String型のTaskを返します。 Task Http.Error Stringという型は、成功時にString型、失敗時にHttp.Error型の結果を返すTaskを表しています。

Taskはその挙動をすることを宣言しているだけで、それ自体では動作しません。 Elmでは、手続き型言語のように、外界に作用する処理をコード中で動作させることができないのです。 そこで、Taskを実際に動作させるためにportという文法を使用します。 portはElmプログラムが外界(JavaScript)とやりとりするための文法で、Task以外にも様々な値をやり取りできます。 ここでは、TaskをJavaScriptの世界に送り出すことで、定義された処理を初期化時に実行しています。

コールバックを扱う

さて、これで非同期通信を走らせることができますが、まだ結果を使っていないので意味がありません。 Elm Architectureに乗るために、何らかのActionを定義してAddressに送りつけてやるのがよいでしょう。

import Http

getData : Task Http.Error String
getData = Http.getString "https://example.com/"

port task : Task () ()
port task =
  getData
    `andThen` (\data -> Signal.send address (Init data))  -- 成功時
    `onError` (\err -> Signal.send address (Error err)) -- 失敗時

ここでしていることは、getDataで得られた結果をInit dataというActionの形でAddressに送りつけています。 また、エラーの場合は同様にError errというActionにしてAddressに送りつけています。

ちなみに、ここで登場しているandThenonErrorは特別なキーワードではなく普通の関数です。 関数や型の詳細については、後述のコラムを参照してください。

サンプル:初期データを非同期で取得する

次に示すのは、初期データを非同期で取得する例です。

import Html exposing (Html, text)
import Http
import Task exposing (Task, andThen, onError)

actions : Signal.Mailbox Action
actions =
  Signal.mailbox NoOp

state : Signal Model
state =
  Signal.foldp update init actions.signal

main : Signal Html
main =
  Signal.map (view actions.address) state

getData : Task Http.Error String
getData = Http.getString "https://example.com/" -- データを取得

port task : Task () ()
port task =
  getData
    `andThen` (\result -> Signal.send actions.address (Init result)) -- 成功時
    `onError` (\err -> Signal.send actions.address (Error (toString err))) -- 失敗時


-- MODEL

type alias Model = String

init : Model
init = "now loading"

-- UPDATE

type Action
  = NoOp
  | Init String
  | Error String

update : Action -> Model -> Model
update action model =
  case action of
    NoOp -> model
    Init result -> result -- 成功時
    Error e -> "error: " ++ e -- 失敗時

-- VIEW

view : Signal.Address Action -> Model -> Html
view address model = text model

なお、このコードはTry Elmでも実行することはできますが、クロスドメイン制約(同一生成元ポリシー)違反でエラーになってしまいます。 成功パターンを試すためには、例えばlocalhostなら同じlocalhostからデータを取得してください。

andThenとonError

Taskの実行結果をコールバック関数で処理するためには、andThenonErrorを使います。

getData : Task Http.Error String
getData = Http.getString "https://example.com/"

port task : Task x ()
port task =
  getData
    `andThen` (\data -> Signal.send address (Init data))
    `onError` (\err -> Signal.send address (Error err))

andThenonErrorは、特別なキーワードではなく普通の関数です。 andThenに付いているバッククォートは、引数の順番を変えて読みやすくするための仕掛けです。 意味は次のように書いているのと同じです。

port task = andThen getData (\data -> Signal.send address (Init data))

andThenの定義は次のようになっています。

andThen : Task x a -> (a -> Task x b) -> Task x b

Taskの処理結果(a)を受け取って新しいTaskを生成するコールバックを渡すことにより、次々とTaskを連鎖できるようになっています。

一方、Signal.sendはAddressに対してデータを送りつける関数です。 Signal.sendの定義は次のようになっています。

send : Address a -> a -> Task x ()

Address宛てにデータを送りつけるという挙動も1つのTaskです。成功時の型は()で、フィードバックがないことを意味しています。

エラー処理はonErrorを使います。使い方はandThenと同様で、エラーを受け取って別のタスクに変換します。

port task : Task () ()
port task =
  getData
    `andThen` (\data -> Signal.send actions.address (Init data))
    `onError` (\e -> Signal.send actions.address (Error e))

なお、Taskを扱う関数は、ここで紹介した他にもたくさんあります。 興味のある方はこちらを参照してください。

次のページ
非同期通信を発生させるコンポーネント

修正履歴

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Webアプリケーション開発技術の新潮流スタディーズ連載記事一覧

もっと読む

この記事の著者

鳥居 陽介(株式会社ワークスアプリケーションズ)(トリイ ヨウスケ)

株式会社ワークスアプリケーションズ所属。イケてるアプリケーションを死ぬほど楽に作るために研究を続ける日々。社内での立ち位置は「フロントエンドのナウい人」。最近エバンジェリストという肩書きが付いた。趣味は作曲とスノーボード。 Blog: http://jinjor-labo.hatenablog.com/ ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8986 2017/03/02 16:39

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング