Перейти к содержанию

Атрибут Async⚓︎

Атрибут #[Async] позволяет выполнять действия параллельно, не ставя их в очередь, что обеспечивает их немедленное выполнение, даже если другие запросы находятся в процессе обработки.

Базовое использование⚓︎

Примените атрибут #[Async] к любому методу действия, который должен выполняться параллельно:

resources/views/components/post/⚡show.blade.php
<?php

use Livewire\Attributes\Async;
use Livewire\Component;
use App\Models\Post;

new class extends Component {
    public Post $post;

    #[Async]
    public function logActivity()
    {
        Activity::log('post-viewed', $this->post);
    }
};
<div wire:intersect="logActivity">
    <!-- Асинхронно логирует активность, когда элемент входит в область видимости -->
</div>

Когда вызывается logActivity(), он выполняется немедленно, не блокируя другие запросы и не блокируясь ими.

Когда использовать⚓︎

Используйте #[Async] для операций типа «выстрелил и забыл», результат которых не влияет на то, что отображается на странице:

  • Аналитика и логирование — отслеживание поведения пользователей, просмотров страниц или взаимодействий.
  • Фоновые операции — запуск задач (jobs), отправка уведомлений или обновление внешних сервисов.
  • Результаты только для JavaScript — получение данных через await $wire.getData(), которые будут использоваться исключительно в JavaScript.

Вот пример отслеживания кликов по внешним ссылкам:

resources/views/components/⚡external-link.blade.php
<?php

use Livewire\Attributes\Async;
use Livewire\Component;

new class extends Component {
    public $url;

    #[Async]
    public function trackClick()
    {
        Analytics::track('external-link-clicked', [
            'url' => $this->url,
            'user_id' => auth()->id(),
        ]);
    }
};
<a href="{{ $url }}" target="_blank" wire:click="trackClick">
    Посетить внешний сайт
</a>

Поскольку отслеживание происходит асинхронно, клик пользователя не задерживается сетевым запросом.

Когда НЕ использовать⚓︎

Асинхронные действия и изменение состояния несовместимы

Никогда не используйте асинхронные действия, если они изменяют состояние компонента, которое отражается в вашем интерфейсе. Поскольку асинхронные действия выполняются параллельно, вы можете столкнуться с непредсказуемыми состояниями гонки, когда состояние вашего компонента расходится в нескольких одновременных запросах.

Рассмотрим этот опасный пример:

resources/views/components/⚡counter.blade.php
// Внимание: Этот фрагмент демонстрирует, как НЕ НУЖНО делать...

<?php

use Livewire\Attributes\Async;
use Livewire\Component;

new class extends Component {
    public $count = 0;

    #[Async] // Не делайте этого!
    public function increment()
    {
        $this->count++; // Изменение состояния в асинхронном действии
    }
};

Если пользователь быстро нажимает кнопку инкремента, одновременно отправляется несколько асинхронных запросов. Каждый запрос начинается с одного и того же начального значения $count, что приводит к потере обновлений. Вы можете нажать 5 раз, но увидите, что счётчик увеличился только на 1.

Золотое правило: Используйте async только для действий, которые выполняют чистые побочные эффекты — операции, не изменяющие свойства, влияющие на представление вашего компонента.

Альтернативный подход⚓︎

Использование модификатора .async⚓︎

Вместо использования атрибута вы можете сделать конкретные вызовы действий асинхронными с помощью модификатора .async:

<button wire:click.async="logActivity">Отследить событие</button>

Этот подход полезен, когда вы хотите, чтобы действие было асинхронным в одних местах, но синхронным в других.

Узнать больше⚓︎

Для получения дополнительной информации об асинхронных действиях, состояниях гонки и продвинутых сценариях использования см. документацию по Действиям.