Skip to content

Async

#[Async] 属性允许操作并行运行而不被排队,使它们即使在其他请求进行中时也能立即执行。

基本用法

#[Async] 属性应用到任何应该并行运行的操作方法上:

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

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

new class extends Component
{
    public Post $post;

    #[Async] // [tl! highlight]
    public function logActivity()
    {
        Activity::log('post-viewed', $this->post);
    }
};
blade
<div wire:intersect="logActivity">
    <!-- 当元素进入视口时异步记录活动 -->
</div>

当调用 logActivity() 时,它会立即执行,不会阻塞其他请求或被其他请求阻塞。

何时使用

对于那些结果不影响页面显示内容的"即发即弃"操作,使用 #[Async]

  • 分析和日志记录 - 跟踪用户行为、页面浏览或交互
  • 后台操作 - 触发任务、发送通知或更新外部服务
  • 仅限 JavaScript 的结果 - 通过 await $wire.getData() 获取数据,这些数据将纯粹由 JavaScript 使用

以下是跟踪外部链接点击的示例:

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

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

new class extends Component
{
    public $url;

    #[Async] // [tl! highlight]
    public function trackClick()
    {
        Analytics::track('external-link-clicked', [
            'url' => $this->url,
            'user_id' => auth()->id(),
        ]);
    }
};
blade
<a href="{{ $url }}" target="_blank" wire:click="trackClick">
    访问外部网站
</a>

由于跟踪是异步发生的,用户的点击不会因网络请求而延迟。

何时不应使用

异步操作和状态变更不能混用

永远不要在修改 UI 中反映的组件状态时使用异步操作。由于异步操作并行运行,您可能会遇到不可预测的竞态条件,导致组件状态在多个同时请求中出现分歧。

请考虑以下危险示例:

php
// 警告:此代码片段展示了不应该做的事情...

<?php // resources/views/components/⚡counter.blade.php

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

new class extends Component
{
    public $count = 0;

    #[Async] // 不要这样做! [tl! highlight]
    public function increment()
    {
        $this->count++; // 在异步操作中修改状态 [tl! highlight]
    }
};

如果用户快速点击递增按钮,多个异步请求会同时触发。每个请求都从相同的初始 $count 值开始,导致更新丢失。您可能点击了 5 次,但只看到计数器递增了 1。

经验法则: 只对执行纯副作用的操作使用异步——即不会改变任何影响组件视图的属性的操作。

替代方法

使用 .async 修饰符

除了使用属性外,您还可以使用 .async 修饰符使特定的操作调用变为异步:

blade
<button wire:click.async="logActivity">跟踪事件</button>

当您希望操作在某些地方是异步的,而在其他地方是同步的时,这种方法很有用。

了解更多

有关异步操作、竞态条件和高级用例的更多信息,请参阅操作文档