پرش به محتویات

HTTP

اغلب اوقات مفید است که اطلاعاتی را از اینترنت دریافت کنیم.

برای نمونه، فرض کنید می‌خواهیم متن کامل کتاب نظریه عمومی اثر والتر لیپمَن را بارگیری کنیم. این کتاب که در سال ۱۹۲۲ منتشر شده است، دیدگاه تاریخی درباره ظهور رسانه‌های جمعی و پیامدهای آن برای دموکراسی را ارایه می‌دهد. در ادامه، روی شیوه استفاده از بسته elm/http برای وارد کردن این کتاب به برنامه‌مان تمرکز خواهیم کرد!

برای مرور این برنامه در ویرایشگر آنلاین، روی دکمه "ویرایش" کلیک کنید. احتمالا قبل از اینکه متن کامل کتاب نمایش داده شود، عبارت "...Loading" نمایش می‌یابد. اکنون روی دکمه ویرایش کلیک کنید!

ویرایش

module Main exposing (..)

import Browser
import Html exposing (Html, pre, text)
import Http



-- MAIN


main =
    Browser.element
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }



-- MODEL


type Model
    = Loading
    | Failure
    | Success String


init : () -> ( Model, Cmd Msg )
init _ =
    ( Loading
    , Http.get
        { url = "https://elm-lang.org/assets/public-opinion.txt"
        , expect = Http.expectString GotText
        }
    )



-- UPDATE


type Msg
    = GotText (Result Http.Error String)


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotText result ->
            case result of
                Err _ ->
                    ( Failure, Cmd.none )

                Ok fullText ->
                    ( Success fullText, Cmd.none )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none



-- VIEW


view : Model -> Html Msg
view model =
    case model of
        Loading ->
            text "Loading..."

        Failure ->
            text "I was unable to load your book."

        Success fullText ->
            pre [] [ text fullText ]

برخی از قسمت‌های برنامه از نمونه‌های قبلی معماری Elm، باید برای شما آشنا باشد. هنوز یک Model از برنامه‌، یک تابع update برای بروزرسانی پیام‌ها و یک تابع view برای بروزرسانی صفحه نمایش داریم.

قسمت‌های جدید، از جمله اضافه شدن تابع subscription، الگوی اصلی که قبلا دیدیم را با برخی تغییرات در توابع init و update گسترش می‌دهند.

init

تابع init چگونگی راه‌اندازی برنامه را توصیف می‌کند:

init : () -> (Model, Cmd Msg)
init _ =
  ( Loading
  , Http.get
      { url = "https://elm-lang.org/assets/public-opinion.txt"
      , expect = Http.expectString GotText
      }
  )

مثل همیشه، باید Model اولیه را تولید کنیم. همچنین اقدام به ایجاد یک دستور، از آنچه می‌خواهیم بلافاصله انجام شود، می‌کنیم. آن دستور در نهایت یک Msg تولید خواهد کرد که به تابع update داده می‌شود.

وبسایت کتاب در حالت Loading شروع می‌شود و می‌خواهیم متن کامل کتاب را دریافت کنیم. هنگام ایجاد درخواست GET با تابع Http.get، نشانی داده‌ای که می‌خواهیم بارگیری شود همراه با نوع آن داده را مشخص و expect می‌کنیم. بنابراین، url به برخی داده‌ها در وبسایت Elm اشاره دارد و انتظار داریم که یک String بزرگ باشد که می‌توانیم روی صفحه نمایش دهیم.

خط Http.expectString GotText نه تنها انتظار ما برای دریافت یک String را مشخص می‌کند، بلکه می‌گوید در زمان دریافت پاسخ، باید به یک پیام GotText تبدیل شود:

type Msg
  = GotText (Result Http.Error String)

-- GotText (Ok "The Project Gutenberg EBook of ...")
-- GotText (Err Http.NetworkError)
-- GotText (Err (Http.BadStatus 404))

توجه داشته باشید که از نوع داده Result استفاده می‌کنیم. این کار، به ما اجازه می‌دهد تا تمام حالت‌های ممکن را در تابع update در نظر بگیریم. نوبت به تابع update رسیده است...

یادداشت

اگر می‌پرسید چرا init یک تابع است (و چرا آرگومانش را نادیده می‌گیریم)، در فصل آینده درباره تعامل با جاوااسکریپت صحبت خواهیم کرد! (آرگومان به ما اجازه می‌دهد تا اطلاعاتی را از جاوااسکریپت در زمان راه‌اندازی اولیه دریافت کنیم.)

update

تابع update نیز اطلاعات بیشتری را برمی‌گرداند:

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    GotText result ->
      case result of
        Err _ ->
          (Failure, Cmd.none)

        Ok fullText ->
          (Success fullText, Cmd.none)

با نگاهی به نشانه‌گذاری نوع داده، می‌بینیم که فقط یک مدل بروز شده را برنمی‌گردانیم. همچنین یک دستور از آنچه می‌خواهیم Elm انجام دهد تولید می‌کنیم.

بطور معمول، برای مرور پیام‌های مختلف از تکنیک تطبیق الگو استفاده می‌کنیم. وقتی یک پیام GotText دریافت می‌شود، Result یا نتیجه درخواست HTTP را بررسی و مدل را بسته به اینکه آیا موفقیت‌آمیز بوده یا خیر، بروزرسانی می‌کنیم. قسمت جدید، افزودن یک دستور به خروجی تابع update است.

در صورتی که خطایی وجود داشته باشد، با فراخوانی دستور Cmd.none نشان می‌دهیم که کار دیگری نمی‌توان انجام داد. متن کامل کتاب دریافت نشده است. در صورتی که متن کامل کتاب را با موفقیت دریافت کردیم، با فراخوانی دستور Cmd.none نشان می‌دهیم که کار دیگری برای انجام دادن وجود ندارد. متن کامل کتاب دریافت شده است! اگر می‌خواستیم کمی پیشرفته‌تر عمل کنیم، می‌توانستیم بر روی Http.Error از تکنیک تطبیق الگو استفاده کرده و در صورت بروز خطای timeout، دوباره درخواست بارگیری کتاب را صادر کنیم.

نکته این است که هر طور تصمیم بگیریم مدل خود را بروزرسانی کنیم، آزاد هستیم که دستورات جدیدی صادر کنیم. من به داده‌های بیشتری نیاز دارم! من یک مقدار تصادفی می‌خواهم! و مواردی از این قبیل.

subscription

مورد جدید دیگری که در این برنامه وجود دارد، تابع subscription است. این تابع به شما اجازه می‌دهد تا به Model نگاه کنید و تصمیم بگیرید آیا می‌خواهید به اطلاعات خاصی مشترک شوید یا خیر. در این برنامه، با استفاده از اشتراک Sub.none نشان می‌دهیم که نیازی به مشترک شدن در جایی نیست، اما به زودی یک نمونه از برنامه ساعت خواهیم دید که در آن به زمان فعلی سیستم مشترک می‌شویم!

خلاصه

هنگام ایجاد یک برنامه با Browser.element، یک سیستم به این شکل راه‌اندازی می‌شود:

Browser.element

در این حالت، توانایی صادر کردن دستور از توابع init و update را به دست می‌آوریم. این کار به ما اجازه می‌دهد تا هر زمان بخواهیم دستور HTTP صادر کنیم. همچنین توانایی مشترک شدن به داده‌های جالب از سمت مرورگر وب را به دست می‌آوریم. (در ادامه یک نمونه از این حالت خواهیم دید!)


یادداشت مترجم

پیاده‌سازی بسته elm/http با استفاده از XMLHttpRequest انجام شده است که یک ویژگی پایدار و شناخته شده در استاندارد ECMAScript به حساب می‌آید. نسخه پنجم این استاندارد، از سال ۲۰۰۹ به بعد در تمام مرورگرهای وب بکار رفته است. برای کسب اطلاعات بیشتر، به منابع زیر مراجعه کنید: