1. Go to this page and download the library: Download lumetas/luper library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
lumetas / luper example snippets
use Luper\Async;
// Создание асинхронной функции из файла
$asyncFunction = Async::create(__DIR__.'/my_function.php');
#+END_SRC
*** Запуск и ожидание результата
#+BEGIN_SRC php
// Запуск с аргументами
$promise = $asyncFunction("arg1", "arg2");
// Проверка завершения
if ($promise->isCompleted()) {
$result = $promise->getResult();
$promise = $asyncFunction(...);
// Неблокирующая отправка данных в дочерний процесс
$promise->sendData('hello');
$promise->sendData(['key' => 'value']);
#+END_SRC
Внутри дочерней функции данные принимаются через luper_get_data().
*** Дочерний процесс -> Родитель
#+begin_src php
return function() {
// Отправка данных родителю
luper_send_data('progress: 50%');
luper_send_data(['status' => 'working']);
return 'final result';
};
#+end_src
Родитель получает их через $promise->getData().
*** Методы
- $promise->sendData($data) - неблокирующая отправка данных в дочерний процесс. Выполнение не останавливается даже при переполнении канала (данные буферизуются).
- $promise->getData(bool $nonBlocking = false) - получить данные от дочернего процесса. По умолчанию ожидает появления данных (внутри файбера приостанавливает его). Если передать true - вернёт null сразу, когда готовых данных нет.
- luper_get_data(bool $nonBlocking = false) - получить данные, отправленные через $promise->sendData(). Семантика та же, что у getData.
- luper_send_data($data) - отправить данные родителю; они попадают в очередь $promise->getData().
*** Пример обмена
#+begin_src php
// worker.php - дочерняя функция
return function(int $count) {
for ($i = 0; $i < $count; $i++) {
luper_send_data("progress: $i/$count");
usleep(100000);
}
$command = luper_get_data(); // ждём команду от родителя
return $command;
};
#+end_src
#+begin_src php
$promise = Async::create(__DIR__ . '/worker.php')(3);
// Читаем промежуточные данные (блокирует, пока данных нет)
var_dump($promise->getData()); // "progress: 0/3"
var_dump($promise->getData()); // "progress: 1/3"
// Неблокирующая проверка: данных ещё нет -> null
var_dump($promise->getData(true));
$promise->sendData('СТАРТ');
var_dump($promise->await()); // "СТАРТ"
#+end_src
** Loop - Цикл событий
Центральный класс для управления асинхронными задачами.
*** Создание экземпляра
#+BEGIN_SRC php
use Luper\Loop;
// Создание нового цикла
$loop = new Loop();
// Или использование синглтона
$loop = Loop::make();
#+END_SRC
*** Добавление задач
#+BEGIN_SRC php
$loop->addTask(function () {
// Ваш код здесь
echo "Выполнено в файбере!";
});
#+END_SRC
*** Таймеры
#+BEGIN_SRC php
// Одноразовый таймер
$timerId = $loop->addTimer(2.5, function () {
echo "Выполнится через 2.5 секунды";
});
// Периодический таймер
$repeatingTimerId = $loop->addTimer(1.0, function () {
echo "Выполняется каждую секунду";
}, true);
// Отмена таймера
$loop->clearTimer($timerId);
#+END_SRC
*** Управление выполнением
#+BEGIN_SRC php
// Запуск цикла
$loop->run();
// Остановка цикла
$loop->stop();
// Приостановка выполнения в файбере
Loop::suspend();
// Задержка выполнения
$loop->sleep(0.5); // sleep на 0.5 секунды
#+END_SRC
* Пример использования
** Базовый пример
#+BEGIN_SRC php
// Файл должен возвращать callable функцию
return function($url) {
// Имитация HTTP-запроса
sleep(1); // Длительная операция
return [
'status' => 200,
'content' => file_get_contents($url),
'headers' => []
];
};
#+END_SRC
* Практические примеры
** Параллельные HTTP-запросы
#+BEGIN_SRC php
use Luper\Async;
use Luper\Loop;
function fetchMultipleUrls(array $urls) {
$loop = new Loop();
$responses = [];
foreach ($urls as $index => $url) {
$loop->addTask(function () use ($url, $index, &$responses, $loop) {
$fetch = Async::create(__DIR__.'/fetch_url.php');
$promise = $fetch($url);
while (!$promise->isCompleted()) {
Loop::suspend();
}
$responses[$index] = $promise->getResult();
});
}
$loop->run();
return $responses;
use Luper\Loop;
$loop = new Loop();
// Обновление кэша каждые 30 секунд
$loop->addTimer(30, function () {
updateCache();
}, true);
// Одноразовая задача через 5 секунд
$loop->addTimer(5, function () {
sendNotification();
});
$loop->run();
#+END_SRC
** closure
#+begin_src php
налом. Чтобы было проще обрабатывать данные Пример:
#+begin_src php
use Luper\Pull;
$items = [];
for($i = 0; count($items) < 50; $i ++) {$items[] = $i;}
$pullSize = 10;
// Создаем пул с максимум 3 параллельными процессами
$pull = new Pull($pullSize, __DIR__.'/proc.php');
// Добавляем задачи
foreach ($items as $item) {
$pull->add($item, 'дополнительный_аргумент');
use Luper\PullMax;
$items = [];
for($i = 0; count($items) < 50; $i ++) {$items[] = $i;}
$pullSize = 10;
$pull = new PullMax(__DIR__.'/proc.php');
// Добавляем задачи
foreach ($items as $item) {
$pull->add($item, 'дополнительный_аргумент');
use Luper\{Loop, Async};
$func = Async::create(__DIR__.'/proc.php');
$loop = new Loop;
$results = [];
foreach ($elems as $elem) {
$loop->addTask(function () use ($func, $loop, &$results) {
$results[] = $func(1, 2)->await();
});
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.