Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala · Pelajaran

Melaksanakan Tingkah Laku GenServer

Kuasai tingkah laku `GenServer` untuk membina proses pelayan berkeadaan yang kukuh dan mengendalikan permintaan secara tak segerak.

Pelajaran 2 daripada 411 langkah

Melaksanakan Tingkah Laku GenServer ialah pelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala merangkumi sejumlah 4 pelajaran.

Kenali GenServer

Selamat datang ke GenServer, blok binaan teras dalam Elixir untuk mencipta proses yang teguh dan mempunyai keadaan!

Anda telah mempelajari tentang proses asas Elixir dan penghantaran mesej. GenServer ialah jenis proses khas yang menyediakan cara piawai untuk mengurus keadaan dan mengendalikan permintaan, sekali gus menjadikan pengaturcaraan serentak lebih mudah.

Ia merupakan sebahagian daripada tingkah laku OTP (Open Telecom Platform) Elixir, yang menawarkan toleransi kesalahan dan struktur yang jelas untuk proses seperti pelayan anda.

Mengapa Menggunakan GenServer?

Penggunaan GenServer menawarkan beberapa kelebihan utama:

  • Antara Muka Piawai: Ia menyediakan antara muka yang konsisten untuk berinteraksi dengan proses.
  • Pengurusan Keadaan: Ia memudahkan penyimpanan dan pengemaskinian data dari semasa ke semasa dalam sesuatu proses.
  • Toleransi Kesalahan: Apabila digunakan bersama penyelia (yang akan dibincangkan kemudian!), GenServer boleh dimulakan semula secara automatik jika ia terhenti akibat ralat.
  • Keserentakan: Ia membolehkan berbilang klien berinteraksi dengan satu proses dengan selamat.

Anggaplah ia sebagai pelayan satu bebenang yang boleh dipercayai untuk data atau operasi anda.

Memulakan GenServer: init/1

Setiap GenServer memulakan hayatnya dengan memanggil GenServer.start_link/3, yang kemudiannya menggunakan fungsi panggil balik init/1. Di sinilah anda menetapkan keadaan awal pelayan anda.

Mari lihat contoh asas:

defmodule MyGenServer do
  use GenServer

  # Client API: How others interact with our GenServer
  def start_link(initial_state) do
    GenServer.start_link(__MODULE__, initial_state, name: __MODULE__)
  end

  # Server Callbacks: What the GenServer does internally
  @impl true
  def init(initial_state) do
    IO.puts "[GenServer] Initializing with: #{inspect initial_state}"
    {:ok, initial_state} # Return {:ok, state} to indicate success
  end
end

# --- Main execution block for runnable example --- 
# Start the GenServer with 'Hello Elixir!' as its initial state
{:ok, pid} = MyGenServer.start_link("Hello Elixir!")
IO.puts "[Main] GenServer started with PID: #{inspect pid}"

# For a simple script, we just start it. In a real app, 
# it would be supervised and run in the background.

Mendapatkan Balasan: handle_call

Apabila anda perlu menghantar permintaan kepada GenServer dan menunggu balasan, gunakan GenServer.call/2. GenServer mengendalikan perkara ini melalui panggil balik handle_call/3.

Ini ialah operasi segerak: kod anda menunggu sehingga GenServer memproses permintaan dan menghantar respons kembali.

defmodule MyGenServer do
  use GenServer

  # Client API
  def start_link(initial_state) do
    GenServer.start_link(__MODULE__, initial_state, name: __MODULE__)
  end

  def get_state do
    GenServer.call(__MODULE__, :get_state)
  end

  # Server Callbacks
  @impl true
  def init(initial_state) do
    {:ok, initial_state}
  end

  @impl true
  def handle_call(:get_state, _from, current_state) do
    IO.puts "[GenServer] Handling :get_state call."
    # {:reply, response_to_client, new_server_state}
    {:reply, current_state, current_state}
  end
end

# --- Main execution block ---
MyGenServer.start_link("Initial Data")
state = MyGenServer.get_state()
IO.puts "[Main] Received state from GenServer: #{inspect state}"

Hantar dan Lupakan: handle_cast

Kadangkala anda hanya mahu menghantar mesej kepada GenServer tanpa menunggu balasan. Dalam keadaan ini, GenServer.cast/2 amat berguna dan dikendalikan oleh panggil balik handle_cast/2.

Ini ialah operasi tak segerak: kod anda menghantar mesej dan terus berjalan serta-merta tanpa menunggu GenServer memprosesnya.

defmodule MyGenServer do
  use GenServer

  # Client API
  def start_link(initial_state) do
    GenServer.start_link(__MODULE__, initial_state, name: __MODULE__)
  end

  def get_state do
    GenServer.call(__MODULE__, :get_state)
  end

  def set_state(new_state) do
    GenServer.cast(__MODULE__, {:set_state, new_state})
  end

  # Server Callbacks
  @impl true
  def init(initial_state) do
    {:ok, initial_state}
  end

  @impl true
  def handle_call(:get_state, _from, current_state) do
    {:reply, current_state, current_state}
  end

  @impl true
  def handle_cast({:set_state, new_state}, _current_state) do
    IO.puts "[GenServer] Handling {:set_state, ...} cast."
    # {:noreply, new_server_state}
    {:noreply, new_state}
  end
end

# --- Main execution block ---
MyGenServer.start_link("Initial Data")
IO.puts "[Main] Current state: #{MyGenServer.get_state()}"
MyGenServer.set_state("Updated Data")
Process.sleep(10) # Give cast a moment to process
IO.puts "[Main] New state after cast: #{MyGenServer.get_state()}"

Keadaan Dalaman GenServer

‘Keadaan’ GenServer hanyalah istilah Elixir (seperti nombor, peta atau senarai) yang dihantar antara fungsi panggil baliknya.

  • init/1 mengembalikan keadaan awal.
  • handle_call/3 mengembalikan keadaan semasa sebagai unsur ketiganya.
  • handle_cast/2 mengembalikan keadaan semasa sebagai unsur keduanya.

Setiap panggil balik menerima keadaan semasa sebagai hujah dan mengembalikan keadaan baharu. Mekanisme mudah ini membolehkan GenServer anda mengekalkan dan mengemas kini data dalamannya dengan boleh dipercayai.

Contoh Praktikal: Pembilang

Mari gabungkan handle_call dan handle_cast untuk membina GenServer pembilang yang mudah. Ia membolehkan kita menambah nilai pembilang (tak segerak) dan mendapatkan nilainya semasa (segerak).

defmodule Counter do
  use GenServer

  # Client API
  def start_link do
    GenServer.start_link(__MODULE__, 0, name: __MODULE__)
  end

  def increment do
    GenServer.cast(__MODULE__, :increment)
  end

  def get_count do
    GenServer.call(__MODULE__, :get_count)
  end

  # Server Callbacks
  @impl true
  def init(initial_count) do
    IO.puts "[Counter] Initialized to: #{initial_count}"
    {:ok, initial_count}
  end

  @impl true
  def handle_cast(:increment, current_count) do
    new_count = current_count + 1
    IO.puts "[Counter] Incremented to: #{new_count}"
    {:noreply, new_count}
  end

  @impl true
  def handle_call(:get_count, _from, current_count) do
    IO.puts "[Counter] Returning current count: #{current_count}"
    {:reply, current_count, current_count}
  end
end

# --- Main execution block ---
Counter.start_link()
IO.puts "[Main] Initial count: #{Counter.get_count()}"
Counter.increment()
Counter.increment()
Process.sleep(10) # Give casts time to process
IO.puts "[Main] Count after increments: #{Counter.get_count()}"

Selain Call dan Cast

Walaupun handle_call dan handle_cast paling lazim digunakan, GenServer mempunyai panggil balik lain:

  • handle_info/2: Untuk mengendalikan mesej umum yang dihantar terus kepada proses (contohnya, menggunakan send/2).
  • terminate/2: Untuk kod pembersihan apabila GenServer hampir berhenti.
  • code_change/3: Untuk mengendalikan naik taraf kod secara langsung tanpa menghentikan pelayan.

Panggil balik ini memberikan lebih banyak kawalan terhadap kitar hayat dan tingkah laku GenServer.

Amalan Terbaik GenServer

Untuk menjadikan GenServer anda berkesan dan mudah diselenggara, pertimbangkan petua ini:

  • API Klien Berasingan: Asingkan fungsi start_link, call dan cast daripada panggil balik @impl.
  • Keadaan Kecil: Cuba pastikan keadaan dalaman GenServer minimum dan mudah.
  • Elakkan Operasi yang Lama: Jangan lakukan tugas yang mengambil masa secara terus dalam panggil balik; tindakan ini boleh menyekat permintaan lain. Gunakan modul Task Elixir untuk kerja sedemikian.
  • Gunakan Nama: Daftarkan GenServer anda dengan nama (contohnya, name: __MODULE__) supaya mudah dicari di seluruh aplikasi.

Pemeriksaan GenServer

Masa untuk soalan ringkas bagi menguji pemahaman anda tentang GenServer!

GenServer: Kesimpulan Utama

Anda telah menguasai asas tingkah laku GenServer!

  • GenServer ialah proses yang mempunyai keadaan untuk mengurus data dan mengendalikan permintaan.
  • init/1 menetapkan keadaan awal.
  • GenServer.call/2 (dikendalikan oleh handle_call/3) digunakan untuk permintaan segerak yang menjangkakan balasan.
  • GenServer.cast/2 (dikendalikan oleh handle_cast/2) digunakan untuk mesej tak segerak yang dihantar tanpa menunggu balasan.
  • Keadaan GenServer dihantar antara panggil balik, membolehkannya berubah dari semasa ke semasa.

GenServer ialah alat yang berkuasa untuk membina aplikasi Elixir yang serentak dan tahan terhadap kegagalan.

Percuma untuk bermula

Pelajari Elixir dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
12
Pelajaran
48

Soalan Lazim

Adakah pelajaran “Melaksanakan Tingkah Laku GenServer” percuma?

Ya — teks penuh “Melaksanakan Tingkah Laku GenServer” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala, tingkat taraf kepada CoddyKit PRO. Kursus Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Melaksanakan Tingkah Laku GenServer”?

Kuasai tingkah laku `GenServer` untuk membina proses pelayan berkeadaan yang kukuh dan mengendalikan permintaan secara tak segerak. Anda berlatih Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Melaksanakan Tingkah Laku GenServer” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala ini?

Ya. Setiap pelajaran Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Proses Elixir dan Penghantaran Mesej
  2. Melaksanakan Tingkah Laku GenServer
  3. Penyelia dan Struktur Aplikasi
  4. Kerja Serentak dengan Task dan Agent
← Kembali ke Elixir & Phoenix: Pembangunan Bahagian Belakang Boleh Skala