Async Action (Future-based)
Penjelasan
Ketika logic di dalam Action melibatkan operasi yang mengembalikan `Future` (query database via Slick, panggilan HTTP ke service lain, dll), `Action.async` dipakai alih-alih `Action` biasa. Bedanya, blok di dalam `Action.async` harus mengembalikan `Future[Result]`, bukan `Result` langsung — Play menunggu Future tersebut selesai secara non-blocking sebelum mengirim response ke klien. Pola ini penting untuk menjaga thread pool Play tetap efisien: karena Future diproses secara non-blocking, thread yang menangani request tidak "diam menunggu" operasi lambat selesai, melainkan bisa dipakai untuk melayani request lain sementara menunggu. Composisi beberapa Future (misalnya query database lalu panggil API eksternal) dilakukan lewat `map`/`flatMap` atau for-comprehension seperti Future biasa di Scala.
Contoh Konsep
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}
import javax.inject._
@Singleton
class ProdukController @Inject()(cc: ControllerComponents, produkService: ProdukService)(implicit ec: ExecutionContext)
extends AbstractController(cc) {
def daftar(): Action[AnyContent] = Action.async {
produkService.ambilSemuaAsync().map { produkList =>
Ok(produkList.mkString(", "))
}
}
}
Praktikum
Buat Action.async detail(id: Long) yang memanggil produkService.cariByIdAsync(id): Future[Option[String]], mengembalikan Ok jika ada, NotFound jika kosong.
Ketik/edit bebas di sini untuk latihan — kode ini tidak dijalankan.
Tips
Selalu pastikan ExecutionContext yang dipakai untuk Future berat (query database) memakai dispatcher terpisah dari default, mirip prinsip dispatcher tuning di Akka, agar operasi lambat tidak mengganggu request lain.