Deferred Functions trong Laravel

Các phiên bản Laravel trước version 11, chúng ta thường sử dụng Queued Jobs cho phép thực hiện sắp xếp các tác vụ xử lý background.

Nhưng đôi khi có những tác vụ đơn giản mà chúng ta muốn defer mà không cần cấu hình hoặc duy trì Queue Worker trong thời gian dài.

Trong version Laravel 11, cung cấp cho chúng ta một hàm Helpers là Deferred Functions cho phép chúng ta defer thực thi closure sau khi HTTP response được gửi tới người dùng, giúp ứng dụng của chúng ta có cảm giác nhanh và phản hổi nhanh chóng.

Tìm hiểu Deferred Functions trong Laravel

Để thử nghiệm tính năng Deferred Functions trong Laravel. Đầu tiên, chúng ta sẽ tạo một command cơ bản với lệnh sau:

php artisan make:command TestDeferredFunctions

Command này sẽ giúp chúng ta có thể so sánh được các sự khác biệt giữa việc không sử dụng Deferred Functions và sử dụng Deferred Functions

Không sử dụng Deferred Functions:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class TestDeferredFunctions extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'app:test-deferred-functions';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Demonstrates the defer functionality in a Laravel command';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $this->info("Starting process.");

        $this->delayedProcess();

        $this->info("Finishing process.");
    }

    /**
     * Delayed process function
     *
     * This method is invoked after a short delay to simulate a background task.
     */
    protected function delayedProcess()
    {
        sleep(10); // Simulates a time-consuming operation
        $this->info("Completed delayed process.");
    }
}

Khi chạy lệnh này, chúng ta sẽ thấy kết quả như sau:

application@5e5ebc1e8817:/app$ php artisan app:test-deferred-functions
Starting process.
Completed delayed process.
Finishing process.

Sử dụng Deferred Functions:

Giờ đây, chúng ta sẽ điều chỉnh command trên để dùng Deferred Functions bằng cách cập nhật hàm handle như sau:

/**
 * Execute the console command.
 */
public function handle()
{
    $this->info("Starting process.");

    defer(fn() => $this->delayedProcess());

    $this->info("Finishing process.");
}

Bây giờ, khi chạy lại lệnh chúng ta sẽ thấy kết quả như sau:

application@5e5ebc1e8817:/app$ php artisan app:test-deferred-functions
Starting process.
Finishing process.
Completed delayed process.

Đối với yêu cầu HTTP thì Deferred Functions sẽ không được thực hiện nếu status của HTTP response là 4xx hoặc 5xx.

Nhưng có thể thay đổi điều này bằng cách sử dụng method always vào Deferred Functions như sau:

Route::get('/test-deferred-functions', function () {
    defer(function () {
        // do time-consuming work here
        sleep(10);
    })->always();

    return "Hello ManhDanBlogs";
});

Nếu bạn cần hủy một Deferred Functions trước khi nó được thực thi, bạn có thể sử dụng method forget để hủy Deferred Functions theo name.

Chúng ta hãy cung cấp đối số thứ hai cho Illuminate\Support\defer như sau để đặt name cho Deferred Functions:

defer(function () {
    // do time-consuming work here
    sleep(10);
}, 'name_defer');

defer()->forget('name_defer');

Sự kì diệu của Deferred Functions trong Laravel

Chúng ta đã tìm hiểu về Deferred Functions thông qua các ví dụ minh họa phía trên, nhưng đối với HTTP requests chúng ta chưa giải thích được cách Deferred Functions được thực hiện sau đó như thế nào phải không?

Thì điều kì diệu đó chỉ thực sự được xảy ra ở Global Middleware mới được thêm vào Core Laravel:

\Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks::class

Nếu nhìn vào mã nguồn Middleware của InvokeDeferredCallbacks thì nó đơn giản là một Terminable Middleware bình thường, nhưng chúng ta hãy để ý đến method terminate sau:

/**
 * Invoke the deferred callbacks.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Symfony\Component\HttpFoundation\Response  $response
 * @return void
 */
public function terminate(Request $request, Response $response)
{
    Container::getInstance()
        ->make(DeferredCallbackCollection::class)
        ->invokeWhen(fn ($callback) => $response->getStatusCode() < 400 || $callback->always);
}

Method terminate đang gọi DeferredCallbackCollection chứa tất cả deferred callbacks được tích lũy trong yêu cầu hiện tại và sẽ được tự động gọi lại sau khi phản hồi về browser.

Đây chính xác là phương pháp mà Laravel có thể thực hiện được Deferred Functions ngay sau khi phản hồi về phía Client.

Với Deferred Functions trong HTTP requests, Laravel đã thực sự tạo ra một phép thuật đặc biệt, giúp cải thiện hiệu suất và trải nghiệm người dùng một cách vượt bậc.

CÓ THỂ BẠN QUAN TÂM

Laravel Queues and Jobs

Laravel Queues and Jobs

Các công ty có thẻ gặp khó khăn trong việc quản lý các dịch vụ hoặc ứng dụng của họ. Ví dụ, các công ty các thực hiện gửi email cho hàng triệu người dùng hoặc thực hiện sao lưu dữ liệu. Tất cả các hoạ...

Google Drive as Filesystem in Laravel

Google Drive as Filesystem in Laravel

Đối với một số dự án, bạn cần phải sử dụng Google Drive (với tài khoản @gmail.com cá nhân hoặc tài khoản G Suite) làm nhà cung cấp bộ nhớ trong các dự án Laravel. Trong bài đăng này, tôi sẽ hướng d...

Laravel TinyMCE 6 Image Upload

Laravel TinyMCE 6 Image Upload

TinyMCE TinyMCE là một trình soạn thảo  WYSIWYG  được xây dựng trên nền tảng Javascript, được phát triển dưới dạng mã nguồn mở theo giấy phép  MIT  bởi Tiny Technologies Inc. TinyMCE cho phép ngư...

Laravel Scout Full Text Search With Meilisearch

Laravel Scout Full Text Search With Meilisearch

Laravel Scout cung cấp một giải pháp đơn giản, dựa trên trình điều khiển để thêm tìm kiếm Full Text vào các mô hình Eloquent của bạn. Khi sử dụng Eloquent, Scout sẽ tự động giữ chỉ mục tìm kiếm của bạ...

Amazon S3 Pre-Signed URL with DropzoneJs in Laravel

Amazon S3 Pre-Signed URL with DropzoneJs in Laravel

Chức năng upload file hay hình ảnh là một chức năng rất phổ biến, hầu hết các dự án đều có chức năng này. Đa số các nhà phát triển khi thực hiện chức năng upload file, thường sẽ sử dụng cách làm nh...

Eloquent Methods: whereDoesntHaveRelation and whereMorphDoesntHaveRelation

Eloquent Methods: whereDoesntHaveRelation and whereMorphDoesntHaveRelation

New Laravel 11.37: Eloquent Methods Laravel cung cấp cho chúng ta khả năng xây dựng các truy vấn dữ liệu mạnh mẽ với Eloquent ORM, giúp chúng ta có thể xử lý các truy vấn cơ sở dữ liệu phức tạp một...

Method WhereAny / WhereAll  in Laravel Eloquent

Method WhereAny / WhereAll in Laravel Eloquent

New Laravel 10: Eloquent WhereAny() và WhereAll() Laravel cung cấp cho chúng ta khả năng xây dựng các truy vấn dữ liệu mạnh mẽ với Eloquent ORM, giúp chúng ta có thể xử lý các truy vấn cơ sở dữ li...

Laravel Jobs Batching

Laravel Jobs Batching

Phiên bản Laravel 8 đã được phát hành với một tính năng mà rất nhiều người trong chúng ta đã chờ đợi rất lâu đó là Jobs Batching, nó cho phép chúng ta thực hiện nhiều công việc trong cùng một lúc và t...

Laravel Custom Eloquent Casts

Laravel Custom Eloquent Casts

Trước đây, chúng ta bị giới hạn cast mặc định do Laravel cung cấp. Mặc dù, có một số gói thư viện có thể  giúp chúng ta custom được nhưng chúng có một nhược điểm lớn. Bởi vì, chúng ghi đề phương thức...

ManhDanBlogs