Perulangan peristiwa reaktor inti ReactPHP yang dapat digunakan perpustakaan untuk peristiwa I/O.
Versi pengembangan: Cabang ini berisi kode untuk rilis v3 mendatang. Untuk kode rilis stabil v1 saat ini, lihat cabang
1.x
Rilis v3 mendatang akan menjadi masa depan untuk paket ini. Namun, kami akan tetap aktif mendukung v1 bagi mereka yang belum menggunakan versi terbaru. Lihat juga petunjuk pemasangan untuk lebih jelasnya.
Agar perpustakaan berbasis async dapat dioperasikan, mereka perlu menggunakan event loop yang sama. Komponen ini menyediakan LoopInterface
umum yang dapat ditargetkan oleh perpustakaan mana pun. Hal ini memungkinkan mereka untuk digunakan dalam loop yang sama, dengan satu panggilan run()
yang dikontrol oleh pengguna.
Daftar isi
Contoh panduan memulai
Penggunaan
berlari()
berhenti()
tambahkanTimer()
tambahkanPeriodicTimer()
pembatalanTimer()
centang masa depan()
tambahkanSinyal()
hapusSinyal()
tambahkanReadStream()
tambahkanWriteStream()
hapusReadStream()
hapusWriteStream()
StreamSelectLoop
ExtEventLoop
ExtEvLoop
ExtUvLoop
Metode lingkaran
Ulangi autorun
mendapatkan()
Lingkaran
Implementasi lingkaran
Antarmuka Lingkaran
Memasang
Tes
Lisensi
Lagi
Berikut adalah server HTTP async yang dibuat hanya dengan loop peristiwa.
<?phpuse ReactEventLoopLoop;membutuhkan __DIR__ . '/vendor/autoload.php';$server = stream_socket_server('tcp://127.0.0.1:8080');stream_set_blocking($server, false); Loop::addReadStream($server, function ($server) {$conn = stream_socket_accept($server);$data = "HTTP/1.1 200 OKrnContent-Length: 3rnrnHin"; Loop::addWriteStream($conn, function ($conn) gunakan (&$data) {$write = fwrite($conn, $data);if ($write === strlen($data)) {fclose($conn ); Loop::removeWriteStream($sambungan); } else {$data = substr($data, $tertulis); } }); }); Loop::addPeriodicTimer(5, function () {$memory = memory_get_usage() / 1024;$formatted = number_format($memory, 3).'K';echo "Penggunaan memori saat ini: {$formatted}n"; });
Lihat juga contohnya.
Aplikasi umum akan menggunakan kelas Loop
untuk menggunakan event loop default seperti ini:
gunakan ReactEventLoopLoop;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Centang' . PHP_EOL; }); Loop::addTimer(1.0, fungsi () gunakan ($timer) { Loop::cancelTimer($timer);echo 'Selesai' . PHP_EOL; });
Sebagai alternatif, Anda juga dapat secara eksplisit membuat instance event loop di awal, menggunakannya kembali di seluruh program Anda dan akhirnya menjalankannya di akhir program seperti ini:
$loop = ReactEventLoopLoop::get();$timer = $loop->addPeriodicTimer(0.1, function () {echo 'Centang' . PHP_EOL; });$loop->addTimer(1.0, function () gunakan ($loop, $timer) {$loop->cancelTimer($timer);echo 'Selesai' . PHP_EOL; });$loop->jalankan();
Meskipun yang pertama lebih ringkas, yang kedua lebih eksplisit. Dalam kedua kasus tersebut, program akan melakukan langkah yang sama persis.
Contoh event loop dibuat di awal program. Hal ini secara implisit dilakukan saat pertama kali Anda memanggil kelas Loop
(atau dengan membuat instance implementasi loop secara manual).
Perulangan peristiwa digunakan secara langsung atau diteruskan sebagai instance ke perpustakaan dan kode aplikasi. Dalam contoh ini, pengatur waktu periodik didaftarkan pada perulangan peristiwa yang hanya mengeluarkan Tick
setiap sepersekian detik hingga pengatur waktu lain menghentikan pengatur waktu periodik setelah satu detik.
Perulangan acara dijalankan di akhir program. Hal ini dilakukan secara otomatis saat menggunakan kelas Loop
atau secara eksplisit dengan satu panggilan run()
di akhir program.
Mulai v1.2.0
, kami sangat menyarankan penggunaan kelas Loop
. Instruksi loop eksplisit masih valid dan mungkin masih berguna dalam beberapa aplikasi, terutama untuk masa transisi menuju gaya yang lebih ringkas.
Kelas Loop
ada sebagai pengakses global yang nyaman untuk loop peristiwa.
Kelas Loop
menyediakan semua metode yang ada di LoopInterface
sebagai metode statis:
berlari()
berhenti()
tambahkanTimer()
tambahkanPeriodicTimer()
pembatalanTimer()
centang masa depan()
tambahkanSinyal()
hapusSinyal()
tambahkanReadStream()
tambahkanWriteStream()
hapusReadStream()
hapusWriteStream()
Jika Anda bekerja dengan loop peristiwa dalam kode aplikasi Anda, sering kali cara termudah adalah dengan berinteraksi langsung dengan metode statis yang ditentukan pada kelas Loop
seperti ini:
gunakan ReactEventLoopLoop;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Centang' . PHP_EOL; }); Loop::addTimer(1.0, fungsi () gunakan ($timer) { Loop::cancelTimer($timer);echo 'Selesai' . PHP_EOL; });
Di sisi lain, jika Anda terbiasa dengan pemrograman berorientasi objek (OOP) dan injeksi ketergantungan (DI), Anda mungkin ingin memasukkan instance loop peristiwa dan memanggil metode instance pada LoopInterface
seperti ini:
gunakan ReactEventLoopLoop; gunakan ReactEventLoopLoopInterface;kelas Greeter {pribadi $loop;fungsi publik __construct(LoopInterface $loop) {$ini->perulangan = $perulangan; }salam fungsi publik(string $nama) {$ini->loop->addTimer(1.0, function () gunakan ($nama) {echo 'Halo ' . $nama . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('Alice');$greeter->greet('Bob');
Setiap panggilan metode statis akan diteruskan apa adanya ke instance loop peristiwa yang mendasarinya dengan menggunakan panggilan Loop::get()
secara internal. Lihat LoopInterface
untuk rincian lebih lanjut tentang metode yang tersedia.
Saat menggunakan kelas Loop
, maka secara otomatis akan mengeksekusi loop di akhir program. Artinya, contoh berikut akan menjadwalkan pengatur waktu dan secara otomatis menjalankan program hingga peristiwa pengatur waktu diaktifkan:
gunakan ReactEventLoopLoop; Loop::addTimer(1.0, function () {echo 'Halo' . PHP_EOL; });
Mulai v1.2.0
, kami sangat menyarankan penggunaan kelas Loop
dengan cara ini dan menghilangkan panggilan run()
eksplisit apa pun. Untuk alasan BC, metode run()
eksplisit masih valid dan mungkin masih berguna dalam beberapa aplikasi, terutama untuk masa transisi menuju gaya yang lebih ringkas.
Jika Anda tidak ingin Loop
berjalan secara otomatis, Anda dapat run()
atau stop()
secara eksplisit. Ini bisa berguna jika Anda menggunakan penangan pengecualian global seperti ini:
gunakan ReactEventLoopLoop; Loop::addTimer(10.0, function() {echo 'Tidak pernah terjadi'; });set_Exception_handler(function (Dapat dilempar $e) {echo 'Kesalahan: ' . $e->getMessage() . PHP_EOL; Ulangi::berhenti(); });lempar RuntimeException baru('Demo');
Metode get(): LoopInterface
dapat digunakan untuk mendapatkan instance event loop yang sedang aktif.
Metode ini akan selalu mengembalikan instance event loop yang sama sepanjang masa aplikasi Anda.
gunakan ReactEventLoopLoop;gunakan ReactEventLoopLoopInterface;$loop = Loop::get();assert($loop instanceof LoopInterface);assert($loop === Loop::get());
Hal ini sangat berguna jika Anda menggunakan pemrograman berorientasi objek (OOP) dan injeksi ketergantungan (DI). Dalam hal ini, Anda mungkin ingin memasukkan instance event loop dan memanggil metode instance di LoopInterface
seperti ini:
gunakan ReactEventLoopLoop; gunakan ReactEventLoopLoopInterface;kelas Greeter {pribadi $loop;fungsi publik __construct(LoopInterface $loop) {$ini->lingkaran = $lingkaran; }salam fungsi publik(string $nama) {$ini->loop->addTimer(1.0, function () gunakan ($nama) {echo 'Halo ' . $nama . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('Alice');$greeter->greet('Bob');
Lihat LoopInterface
untuk rincian lebih lanjut tentang metode yang tersedia.
Selain LoopInterface
, ada sejumlah implementasi event loop yang disediakan.
Semua loop acara mendukung fitur berikut:
Jajak pendapat deskriptor file
Pengatur waktu satu kali
Pengatur waktu berkala
Eksekusi yang ditangguhkan pada centang loop berikutnya
Bagi sebagian besar konsumen paket ini, implementasi event loop yang mendasarinya adalah detail implementasi. Anda harus menggunakan kelas Loop
untuk membuat instance baru secara otomatis.
Canggih! Jika Anda secara eksplisit memerlukan implementasi loop peristiwa tertentu, Anda dapat membuat instance salah satu kelas berikut secara manual. Perhatikan bahwa Anda mungkin harus menginstal ekstensi PHP yang diperlukan untuk masing-masing implementasi loop peristiwa terlebih dahulu atau ekstensi tersebut akan memunculkan BadMethodCallException
saat pembuatan.
Perulangan peristiwa berbasis stream_select()
.
Ini menggunakan fungsi stream_select()
dan merupakan satu-satunya implementasi yang dapat langsung digunakan dengan PHP.
Perulangan peristiwa ini berfungsi langsung pada versi PHP apa pun. Ini berarti tidak diperlukan instalasi dan perpustakaan ini berfungsi di semua platform dan mendukung versi PHP. Oleh karena itu, kelas Loop
akan menggunakan loop peristiwa ini secara default jika Anda tidak menginstal ekstensi loop peristiwa apa pun yang tercantum di bawah.
Di bawah tenda, ia melakukan panggilan sistem select
sederhana. Panggilan sistem ini dibatasi pada jumlah deskriptor file maksimum FD_SETSIZE
(tergantung platform, biasanya 1024) dan berskala dengan O(m)
( m
adalah jumlah deskriptor file maksimum yang diteruskan). Ini berarti Anda mungkin mengalami masalah saat menangani ribuan aliran secara bersamaan dan Anda mungkin ingin mempertimbangkan penggunaan salah satu implementasi loop peristiwa alternatif yang tercantum di bawah dalam kasus ini. Jika kasus penggunaan Anda termasuk di antara banyak kasus penggunaan umum yang hanya melibatkan penanganan lusinan atau beberapa ratus aliran sekaligus, maka implementasi loop peristiwa ini akan bekerja dengan sangat baik.
Jika Anda ingin menggunakan penanganan sinyal (lihat juga addSignal()
di bawah), implementasi event loop ini memerlukan ext-pcntl
. Ekstensi ini hanya tersedia untuk platform mirip Unix dan tidak mendukung Windows. Ini biasanya diinstal sebagai bagian dari banyak distribusi PHP. Jika ekstensi ini tidak ada (atau Anda menjalankannya di Windows), penanganan sinyal tidak didukung dan malah menampilkan BadMethodCallException
.
Perulangan peristiwa ini diketahui mengandalkan waktu jam dinding untuk menjadwalkan pengatur waktu mendatang saat menggunakan versi apa pun sebelum PHP 7.3, karena sumber waktu monoton hanya tersedia pada PHP 7.3 ( hrtime()
). Meskipun hal ini tidak mempengaruhi banyak kasus penggunaan umum, hal ini merupakan perbedaan penting untuk program yang mengandalkan presisi waktu yang tinggi atau pada sistem yang tunduk pada penyesuaian waktu yang terputus-putus (lompatan waktu). Artinya jika Anda menjadwalkan pengatur waktu untuk terpicu dalam 30 detik pada PHP <7.3 dan kemudian menyesuaikan waktu sistem Anda sebanyak 20 detik, pengatur waktu tersebut dapat terpicu dalam 10 detik. Lihat juga addTimer()
untuk lebih jelasnya.
Perulangan peristiwa berbasis ext-event
.
Ini menggunakan ekstensi event
PECL, yang menyediakan antarmuka ke perpustakaan libevent
. libevent
sendiri mendukung sejumlah backend khusus sistem (epoll, kqueue).
Loop ini diketahui bekerja dengan PHP 7.1 hingga PHP 8+.
Perulangan peristiwa berbasis ext-ev
.
Loop ini menggunakan ekstensi ev
PECL, yang menyediakan antarmuka ke perpustakaan libev
. libev
sendiri mendukung sejumlah backend khusus sistem (epoll, kqueue).
Loop ini diketahui bekerja dengan PHP 7.1 hingga PHP 8+.
Perulangan acara berbasis ext-uv
.
Loop ini menggunakan ekstensi uv
PECL, yang menyediakan antarmuka ke perpustakaan libuv
. libuv
sendiri mendukung sejumlah backend khusus sistem (epoll, kqueue).
Loop ini diketahui bekerja dengan PHP 7.1 hingga PHP 8+.
Metode run(): void
dapat digunakan untuk menjalankan perulangan peristiwa hingga tidak ada lagi tugas yang harus dilakukan.
Bagi banyak aplikasi, metode ini adalah satu-satunya pemanggilan yang terlihat langsung pada loop peristiwa. Sebagai aturan praktis, biasanya disarankan untuk melampirkan semuanya ke instance loop yang sama dan kemudian menjalankan loop satu kali di ujung bawah aplikasi.
$loop->jalankan();
Metode ini akan menjaga loop tetap berjalan hingga tidak ada lagi tugas yang harus dilakukan. Dengan kata lain: Metode ini akan memblokir hingga pengatur waktu, aliran, dan/atau sinyal terakhir dihapus.
Demikian pula, penting untuk memastikan aplikasi benar-benar memanggil metode ini satu kali. Menambahkan pendengar ke loop dan tidak menjalankannya akan mengakibatkan aplikasi keluar tanpa benar-benar menunggu pendengar yang terpasang.
Metode ini TIDAK BOLEH dipanggil saat loop sedang berjalan. Metode ini MUNGKIN dipanggil lebih dari sekali setelah secara eksplisit stop()
ped atau setelah dihentikan secara otomatis karena sebelumnya tidak ada hubungannya lagi.
Metode stop(): void
dapat digunakan untuk memerintahkan perulangan peristiwa yang sedang berjalan agar berhenti.
Metode ini dianggap sebagai penggunaan tingkat lanjut dan harus digunakan dengan hati-hati. Sebagai aturan praktis, biasanya disarankan untuk membiarkan perulangan berhenti secara otomatis ketika tidak ada hubungannya lagi.
Metode ini dapat digunakan untuk secara eksplisit memerintahkan perulangan peristiwa untuk berhenti:
$loop->addTimer(3.0, fungsi () gunakan ($loop) {$loop->stop(); });
Memanggil metode ini pada instance loop yang sedang tidak berjalan atau pada instance loop yang telah dihentikan tidak akan berpengaruh.
addTimer(float $interval, callable $callback): TimerInterface
dapat digunakan untuk mengantrekan callback agar dipanggil satu kali setelah interval yang ditentukan.
Parameter kedua HARUS berupa fungsi panggilan balik pengatur waktu yang menerima instance pengatur waktu sebagai satu-satunya parameternya. Jika Anda tidak menggunakan instance pengatur waktu di dalam fungsi panggilan balik pengatur waktu, Anda MUNGKIN menggunakan fungsi yang tidak memiliki parameter sama sekali.
Fungsi panggilan balik pengatur waktu TIDAK HARUS mengeluarkan Exception
. Nilai yang dikembalikan dari fungsi panggilan balik pengatur waktu akan diabaikan dan tidak berpengaruh, jadi demi alasan performa, Anda disarankan untuk tidak mengembalikan struktur data yang berlebihan.
Metode ini mengembalikan contoh pengatur waktu. Contoh pengatur waktu yang sama juga akan diteruskan ke fungsi panggilan balik pengatur waktu seperti dijelaskan di atas. Anda dapat memanggil cancelTimer
untuk membatalkan timer yang tertunda. Berbeda dengan addPeriodicTimer()
, metode ini akan memastikan callback hanya akan dipanggil satu kali setelah interval tertentu.
$loop->addTimer(0.8, function () {echo 'dunia!' . PHP_EOL; });$loop->addTimer(0.3, fungsi () {echo 'halo '; });
Lihat juga contoh #1.
Jika Anda ingin mengakses variabel apa pun dalam fungsi panggilan balik, Anda dapat mengikat data arbitrer ke penutupan panggilan balik seperti ini:
fungsi halo($nama, LoopInterface $loop) {$loop->addTimer(1.0, function () gunakan ($nama) {echo "halo $nama"; }); }halo('Penguji', $loop);
Antarmuka ini tidak menerapkan resolusi pengatur waktu tertentu, jadi perhatian khusus mungkin harus diberikan jika Anda mengandalkan presisi sangat tinggi dengan akurasi milidetik atau lebih rendah. Implementasi event loop HARUS bekerja berdasarkan upaya terbaik dan HARUS memberikan akurasi setidaknya milidetik kecuali dinyatakan lain. Banyak implementasi event loop yang diketahui memberikan akurasi mikrodetik, namun secara umum tidak disarankan untuk mengandalkan presisi tinggi ini.
Demikian pula, urutan eksekusi pengatur waktu yang dijadwalkan untuk dieksekusi pada waktu yang sama (sesuai keakuratannya) tidak dijamin.
Antarmuka ini menyarankan bahwa implementasi event loop HARUS menggunakan sumber waktu monotonik jika tersedia. Mengingat bahwa sumber waktu monotonik hanya tersedia pada PHP 7.3 secara default, implementasi event loop MUNGKIN kembali menggunakan waktu jam dinding. Meskipun hal ini tidak mempengaruhi banyak kasus penggunaan umum, hal ini merupakan perbedaan penting untuk program yang mengandalkan presisi waktu yang tinggi atau pada sistem yang tunduk pada penyesuaian waktu yang terputus-putus (lompatan waktu). Ini berarti bahwa jika Anda menjadwalkan pengatur waktu untuk terpicu dalam 30 detik dan kemudian menyesuaikan waktu sistem Anda maju sebanyak 20 detik, pengatur waktu tersebut HARUS tetap terpicu dalam 30 detik. Lihat juga implementasi event loop untuk lebih jelasnya.
Metode addPeriodicTimer(float $interval, callable $callback): TimerInterface
dapat digunakan untuk mengantrekan panggilan balik agar dipanggil berulang kali setelah interval yang ditentukan.
Parameter kedua HARUS berupa fungsi panggilan balik pengatur waktu yang menerima instance pengatur waktu sebagai satu-satunya parameternya. Jika Anda tidak menggunakan instance pengatur waktu di dalam fungsi panggilan balik pengatur waktu, Anda MUNGKIN menggunakan fungsi yang tidak memiliki parameter sama sekali.
Fungsi panggilan balik pengatur waktu TIDAK HARUS mengeluarkan Exception
. Nilai yang dikembalikan dari fungsi panggilan balik pengatur waktu akan diabaikan dan tidak berpengaruh, jadi demi alasan performa, Anda disarankan untuk tidak mengembalikan struktur data yang berlebihan.
Metode ini mengembalikan contoh pengatur waktu. Contoh pengatur waktu yang sama juga akan diteruskan ke fungsi panggilan balik pengatur waktu seperti dijelaskan di atas. Tidak seperti addTimer()
, metode ini akan memastikan callback akan dipanggil tanpa batas waktu setelah interval tertentu atau hingga Anda memanggil cancelTimer
.
$timer = $loop->addPeriodicTimer(0.1, function () {echo 'centang!' . PHP_EOL; });$loop->addTimer(1.0, function () gunakan ($loop, $timer) {$loop->cancelTimer($timer);echo 'Selesai' . PHP_EOL; });
Lihat juga contoh #2.
Jika Anda ingin membatasi jumlah eksekusi, Anda dapat mengikat data arbitrer ke penutupan panggilan balik seperti ini:
fungsi halo($nama, LoopInterface $loop) {$n = 3;$loop->addPeriodicTimer(1.0, fungsi ($timer) gunakan ($nama, $loop, &$n) {if ($n > 0) { --$n;echo "halo $nama"; } else {$loop->cancelTimer($timer); } }); }halo('Penguji', $loop);
Antarmuka ini tidak menerapkan resolusi pengatur waktu tertentu, jadi perhatian khusus mungkin harus diberikan jika Anda mengandalkan presisi sangat tinggi dengan akurasi milidetik atau lebih rendah. Implementasi event loop HARUS bekerja berdasarkan upaya terbaik dan HARUS memberikan akurasi setidaknya milidetik kecuali dinyatakan lain. Banyak implementasi event loop yang diketahui memberikan akurasi mikrodetik, namun secara umum tidak disarankan untuk mengandalkan presisi tinggi ini.
Demikian pula, urutan eksekusi pengatur waktu yang dijadwalkan untuk dieksekusi pada waktu yang sama (sesuai keakuratannya) tidak dijamin.
Antarmuka ini menyarankan bahwa implementasi event loop HARUS menggunakan sumber waktu monotonik jika tersedia. Mengingat bahwa sumber waktu monotonik hanya tersedia pada PHP 7.3 secara default, implementasi event loop MUNGKIN kembali menggunakan waktu jam dinding. Meskipun hal ini tidak mempengaruhi banyak kasus penggunaan umum, hal ini merupakan perbedaan penting untuk program yang mengandalkan presisi waktu yang tinggi atau pada sistem yang tunduk pada penyesuaian waktu yang terputus-putus (lompatan waktu). Ini berarti bahwa jika Anda menjadwalkan pengatur waktu untuk terpicu dalam 30 detik dan kemudian menyesuaikan waktu sistem Anda maju sebanyak 20 detik, pengatur waktu tersebut HARUS tetap terpicu dalam 30 detik. Lihat juga implementasi event loop untuk lebih jelasnya.
Selain itu, pengatur waktu periodik dapat mengalami penyimpangan pengatur waktu karena penjadwalan ulang setelah setiap pemanggilan. Oleh karena itu, umumnya tidak disarankan untuk mengandalkan ini untuk interval presisi tinggi dengan akurasi milidetik atau lebih rendah.
Metode cancelTimer(TimerInterface $timer): void
dapat digunakan untuk membatalkan timer yang tertunda.
Lihat juga addPeriodicTimer()
dan contoh #2.
Memanggil metode ini pada instance pengatur waktu yang belum ditambahkan ke instance loop ini atau pada pengatur waktu yang telah dibatalkan tidak akan berpengaruh.
Metode futureTick(callable $listener): void
dapat digunakan untuk menjadwalkan panggilan balik yang akan dipanggil pada tick masa depan dari loop peristiwa.
Cara kerjanya sangat mirip dengan pengatur waktu dengan interval nol detik, namun tidak memerlukan overhead penjadwalan antrian pengatur waktu.
Fungsi tick callback HARUS dapat menerima parameter nol.
Fungsi panggilan balik centang TIDAK HARUS memunculkan Exception
. Nilai yang dikembalikan dari fungsi panggilan balik centang akan diabaikan dan tidak berpengaruh, jadi demi alasan kinerja, Anda disarankan untuk tidak mengembalikan struktur data yang berlebihan.
Jika Anda ingin mengakses variabel apa pun dalam fungsi panggilan balik, Anda dapat mengikat data arbitrer ke penutupan panggilan balik seperti ini:
fungsi halo($nama, LoopInterface $loop) {$loop->futureTick(function () use ($name) {echo "halo $nama"; }); }halo('Penguji', $loop);
Tidak seperti pengatur waktu, callback tick dijamin akan dieksekusi sesuai urutan antreannya. Selain itu, setelah panggilan balik dilakukan, tidak ada cara untuk membatalkan operasi ini.
Hal ini sering digunakan untuk memecah tugas-tugas yang lebih besar menjadi langkah-langkah yang lebih kecil (suatu bentuk multitasking kooperatif).
$loop->futureTick(fungsi () {echo 'b'; });$loop->futureTick(fungsi () {echo 'c'; });gema 'a';
Lihat juga contoh #3.
Metode addSignal(int $signal, callable $listener): void
dapat digunakan untuk mendaftarkan pendengar agar diberi tahu ketika sinyal telah ditangkap oleh proses ini.
Ini berguna untuk menangkap sinyal interupsi pengguna atau sinyal mematikan dari alat seperti supervisor
atau systemd
.
Parameter kedua HARUS berupa fungsi panggilan balik pendengar yang menerima sinyal sebagai satu-satunya parameternya. Jika Anda tidak menggunakan sinyal di dalam fungsi panggilan balik pendengar, Anda MUNGKIN menggunakan fungsi yang tidak memiliki parameter sama sekali.
Fungsi panggilan balik pendengar TIDAK BOLEH memunculkan Exception
. Nilai yang dikembalikan dari fungsi callback pendengar akan diabaikan dan tidak berpengaruh, jadi demi alasan performa, Anda disarankan untuk tidak mengembalikan struktur data yang berlebihan.
$loop->addSignal(SIGINT, function (int $signal) {echo 'Sinyal interupsi pengguna tertangkap' . PHP_EOL; });
Lihat juga contoh #4.
Signaling hanya tersedia pada platform mirip Unix, Windows tidak didukung karena keterbatasan sistem operasi. Metode ini mungkin memunculkan BadMethodCallException
jika sinyal tidak didukung pada platform ini, misalnya ketika ekstensi yang diperlukan tidak ada.
Catatan: Seorang pendengar hanya dapat ditambahkan satu kali ke sinyal yang sama, segala upaya untuk menambahkannya lebih dari satu kali akan diabaikan.
Metode removeSignal(int $signal, callable $listener): void
dapat digunakan untuk menghapus pendengar sinyal yang ditambahkan sebelumnya.
$loop->removeSignal(SIGINT, $listener);
Segala upaya untuk menghapus pendengar yang tidak terdaftar akan diabaikan.
Canggih! Perhatikan bahwa API tingkat rendah ini dianggap sebagai penggunaan tingkat lanjut. Sebagian besar kasus penggunaan mungkin sebaiknya menggunakan Stream API tingkat tinggi yang dapat dibaca.
Metode addReadStream(resource $stream, callable $callback): void
dapat digunakan untuk mendaftarkan pendengar agar diberi tahu ketika aliran siap dibaca.
Parameter pertama HARUS berupa sumber daya aliran valid yang mendukung pemeriksaan apakah siap dibaca oleh implementasi loop ini. Sumber daya aliran tunggal TIDAK BOLEH ditambahkan lebih dari satu kali. Sebagai gantinya, panggil removeReadStream()
terlebih dahulu atau tanggapi peristiwa ini dengan satu pendengar, lalu kirim dari pendengar ini. Metode ini MUNGKIN memunculkan Exception
jika jenis sumber daya yang diberikan tidak didukung oleh implementasi loop ini.
Parameter kedua HARUS berupa fungsi panggilan balik pendengar yang menerima sumber daya aliran sebagai satu-satunya parameternya. Jika Anda tidak menggunakan sumber daya aliran di dalam fungsi panggilan balik pendengar, Anda MUNGKIN menggunakan fungsi yang tidak memiliki parameter sama sekali.
Fungsi panggilan balik pendengar TIDAK BOLEH memunculkan Exception
. Nilai yang dikembalikan dari fungsi callback pendengar akan diabaikan dan tidak berpengaruh, jadi demi alasan performa, Anda disarankan untuk tidak mengembalikan struktur data yang berlebihan.
Jika Anda ingin mengakses variabel apa pun dalam fungsi panggilan balik, Anda dapat mengikat data arbitrer ke penutupan panggilan balik seperti ini:
$loop->addReadStream($stream, function ($stream) use ($name) {echo $name . ' berkata: ' . fread($stream); });
Lihat juga contoh #11.
Anda dapat memanggil removeReadStream()
untuk menghapus event read-reader untuk aliran ini.
Urutan eksekusi pemroses ketika beberapa streaming siap pada saat yang sama tidak dijamin.
Beberapa implementasi event loop diketahui hanya memicu pendengar jika aliran dapat dibaca (dipicu oleh tepi) dan mungkin tidak terpicu jika aliran sudah dapat dibaca dari awal. Hal ini juga menyiratkan bahwa aliran mungkin tidak dikenali sebagai dapat dibaca ketika data masih tersisa di buffer aliran internal PHP. Oleh karena itu, disarankan untuk menggunakan stream_set_read_buffer($stream, 0);
untuk menonaktifkan buffer baca internal PHP dalam kasus ini.
Canggih! Perhatikan bahwa API tingkat rendah ini dianggap sebagai penggunaan tingkat lanjut. Sebagian besar kasus penggunaan mungkin sebaiknya menggunakan Stream API tingkat tinggi yang dapat ditulisi.
Metode addWriteStream(resource $stream, callable $callback): void
dapat digunakan untuk mendaftarkan pendengar agar diberi tahu ketika aliran siap untuk ditulis.
Parameter pertama HARUS berupa sumber daya aliran valid yang mendukung pemeriksaan apakah siap untuk ditulis dengan implementasi loop ini. Sumber daya aliran tunggal TIDAK BOLEH ditambahkan lebih dari satu kali. Sebagai gantinya, panggil removeWriteStream()
terlebih dahulu atau tanggapi peristiwa ini dengan satu pendengar, lalu kirim dari pendengar ini. Metode ini MUNGKIN memunculkan Exception
jika jenis sumber daya yang diberikan tidak didukung oleh implementasi loop ini.
Parameter kedua HARUS berupa fungsi panggilan balik pendengar yang menerima sumber daya aliran sebagai satu-satunya parameternya. Jika Anda tidak menggunakan sumber daya aliran di dalam fungsi panggilan balik pendengar, Anda MUNGKIN menggunakan fungsi yang tidak memiliki parameter sama sekali.
Fungsi panggilan balik pendengar TIDAK BOLEH memunculkan Exception
. Nilai yang dikembalikan dari fungsi callback pendengar akan diabaikan dan tidak berpengaruh, jadi demi alasan performa, Anda disarankan untuk tidak mengembalikan struktur data yang berlebihan.
Jika Anda ingin mengakses variabel apa pun dalam fungsi panggilan balik, Anda dapat mengikat data arbitrer ke penutupan panggilan balik seperti ini:
$loop->addWriteStream($stream, function ($stream) use ($name) {fwrite($stream, 'Halo ' . $name); });
Lihat juga contoh #12.
Anda dapat memanggil removeWriteStream()
untuk menghapus event write-listener untuk aliran ini.
Urutan eksekusi pemroses ketika beberapa streaming siap pada saat yang sama tidak dijamin.
Metode removeReadStream(resource $stream): void
dapat digunakan untuk menghapus pendengar acara baca untuk aliran tertentu.
Menghapus aliran dari loop yang telah dihapus atau mencoba menghapus aliran yang tidak pernah ditambahkan atau tidak valid tidak akan berpengaruh.
Metode removeWriteStream(resource $stream): void
dapat digunakan untuk menghapus pendengar acara tulis untuk aliran tertentu.
Menghapus aliran dari loop yang telah dihapus atau mencoba menghapus aliran yang tidak pernah ditambahkan atau tidak valid tidak akan berpengaruh.
Cara yang disarankan untuk menginstal perpustakaan ini adalah melalui Komposer. Baru mengenal Komposer?
Setelah dirilis, proyek ini akan mengikuti SemVer. Saat ini, ini akan menginstal versi pengembangan terbaru:
komposer memerlukan reaksi/loop peristiwa:^3@dev
Lihat juga CHANGELOG untuk detail tentang peningkatan versi.
Proyek ini bertujuan untuk berjalan pada platform apa pun sehingga tidak memerlukan ekstensi PHP apa pun dan mendukung berjalan pada PHP 7.1 hingga PHP 8+ saat ini. Sangat disarankan untuk menggunakan versi PHP terbaru yang didukung untuk proyek ini.
Menginstal salah satu ekstensi loop peristiwa disarankan, tetapi sepenuhnya opsional. Lihat juga implementasi event loop untuk lebih jelasnya.
Untuk menjalankan test suite, Anda harus mengkloning repo ini terlebih dahulu, lalu menginstal semua dependensi melalui Composer:
instalasi komposer
Untuk menjalankan rangkaian pengujian, buka root proyek dan jalankan:
vendor/bin/phpunit
MIT, lihat file LISENSI.
Lihat komponen Stream kami untuk informasi lebih lanjut tentang bagaimana stream digunakan dalam aplikasi dunia nyata.
Lihat wiki pengguna kami dan tanggungan di Packagist untuk daftar paket yang menggunakan EventLoop dalam aplikasi dunia nyata.