Siti sedang mencari cabang toko Budi yang paling dekat. Daftar cabang memang tersedia, tetapi tersusun alfabetis — tidak membantu bagi siapa pun yang hanya ingin tahu “yang terdekat dari posisi saya sekarang”. Browser punya jawaban untuk kebutuhan ini: Geolocation API, yang membaca posisi perangkat dari sumber seperti Wi-Fi, seluler, atau GPS, lalu menyerahkannya ke JavaScript — asalkan pengguna menyetujuinya.

Perizinan bukan pelengkap, melainkan inti desain API ini: posisi adalah data yang sensitif, sehingga setiap permintaan muncul lebih dulu sebagai dialog pilihan di tangan pengunjung. Konsekuensinya, kode kita selalu menyiapkan dua jalur: callback sukses yang menerima posisi, dan callback galat yang menerima penolakan maupun kegagalan pengukuran.

Meminta Posisi dengan getCurrentPosition #

Aturannya: navigator.geolocation.getCurrentPosition(sukses, galat, opsi) meminta satu kali pembacaan posisi. Kedua callback wajib disiapkan; opsi ketiga bersifat pilihan. Karena prosesnya butuh waktu — dialog harus dijawab, sumber posisi harus dikonsultasi — hasilnya dikirim lewat callback, bukan sebagai nilai kembali:

// posisi-pengguna.js — membaca posisi perangkat dengan izin pengguna
// Geolocation API hanya ada di browser;
// berkas ini lolos node --check dan dijalankan pada halaman toko.

const tombolCari = document.querySelector("#cari-toko");
const panelHasil = document.querySelector("#hasil-toko");

tombolCari.addEventListener("click", () => {
  panelHasil.textContent = "Mencari posisi...";

  navigator.geolocation.getCurrentPosition(
    // callback sukses: object GeolocationPosition
    (posisi) => {
      const { latitude, longitude } = posisi.coords;
      console.log(`Posisi: ${latitude.toFixed(4)}, ${longitude.toFixed(4)}`);
      panelHasil.textContent = "Toko terdekat: Cabang Semporna (2,1 km)";
    },
    // callback galat: object GeolocationPositionError
    (error) => {
      console.log("Gagal, kode:", error.code, "-", error.message);
      panelHasil.textContent = "Posisi tidak tersedia. Pilih toko secara manual.";
    },
    { timeout: 8000, maximumAge: 60000, enableHighAccuracy: false }
  );
});

Geolocation API tidak tersedia di Node maupun jsdom, sehingga berkas ini diverifikasi sintaksnya dengan node --check posisi-pengguna.js; keluaran berikut dicatat sebagai keluaran console browser sesuai perilaku standar. Ketika Siti menekan tombol dan menyetujui dialog izin, console mencatat:

Keluaran console browser:

text
Posisi: -6.2146, 106.8451

Mari kita telaah baris-baris pentingnya:

  1. Baris 8 (addEventListener("click", ...)): permintaan posisi dikaitkan dengan aksi pengunjung — tombol “Cari toko terdekat”. Browser menampilkan dialog izin pada saat itu, dan teks tombol sekaligus menjelaskan mengapa posisi diminta.
  2. Baris 11 (getCurrentPosition(...)): permintaan dikirim ke browser. Tidak ada nilai posisi yang dikembalikan langsung; kedua callback di baris berikutnya yang menerima hasilnya.
  3. Baris 13–17 (callback sukses): parameter posisi berupa object GeolocationPosition. Properti coords memuat latitude, longitude, accuracy (akurasi dalam meter), dan — bila tersedia — altitude, heading, serta speed. toFixed(4) membulatkan koordinat untuk tampilan.
  4. Baris 19–22 (callback galat): parameter error berupa GeolocationPositionError dengan code dan message. Panel tidak dibiarkan kosong — pesan “pilih toko secara manual” memberi jalur lanjutan bagi pengunjung yang menolak.
  5. Baris 23 (object opsi): timeout: 8000 membatasi penantian delapan detik, maximumAge: 60000 menerima posisi cache hingga usia satu menit, dan enableHighAccuracy: false memilih sumber yang hemat energi untuk kebutuhan “toko terdekat”.

Callback Galat dan Kode Kesalahannya #

Tiga kode galat resmi menutup semua jalur kegagalan, dan masing-masing menuntut reaksi yang berbeda:

KodeNamaPenyebab khas
1PERMISSION_DENIEDpengunjung menolak dialog izin, atau izin sudah berstatus ditolak
2POSITION_UNAVAILABLEperangkat tidak bisa menentukan posisi — sumber tidak ada atau sinyal tidak memadai
3TIMEOUTbatas options.timeout terlampaui sebelum posisi diperoleh

Teks error.message berbeda-beda antar browser dan berubah-ubah antar versi, jadi jadikan error.code acuan keputusan dan error.message hanya sebagai catatan di console. Untuk PERMISSION_DENIED, UI yang baik tidak mengulang permintaan secara paksa — pengunjung sudah berbicara; tawarkan pilihan manual seperti yang ditulis panel pada contoh. Untuk TIMEOUT, pemanggilan ulang dengan enableHighAccuracy: false sering berhasil karena sumber yang lebih cepat dipilih. Dengan izin yang ditolak, keluaran console pada contoh di atas berubah menjadi:

Keluaran console browser:

text
Gagal, kode: 1 - User denied Geolocation

Opsi Pencarian dan watchPosition #

Object opsi menyeimbangkan kecepatan, akurasi, dan konsumsi daya:

OpsiArtiNilai default
timeoutbatas waktu tunggu posisi, dalam milidetiktak terbatas
maximumAgeusia maksimum posisi cache yang masih boleh dipakai, dalam milidetik0 (selalu posisi baru)
enableHighAccuracymemilih sumber paling akurat (misalnya GPS) — lebih teliti tetapi lebih lambat dan lebih haus dayafalse

Kombinasi yang lazim: maximumAge besar untuk fitur yang tidak butuh ketelitian tinggi (posisi cache dijawab nyaris seketika), dan timeout wajar seperti 8–10 detik agar UI tidak menunggu tanpa batas. Permintaan pertama dengan maximumAge: 60000 bisa terjawab dari cache tanpa dialog tambahan, asalkan posisi pernah dibaca dalam satu menit terakhir.

Untuk fitur yang mengikuti pergerakan — melacak kurir yang sedang mengantar paket, misalnya — tersedia watchPosition(sukses, galat, opsi) dengan bentuk argumen yang sama persis. Perbedaannya pada perilaku: callback sukses dipanggil ulang setiap kali posisi berubah, dan nilai kembalian berupa angka id yang digunakan clearWatch(id) untuk menghentikan pelacakan. Aturan privasinya tidak berubah: API ini hanya aktif pada secure context (HTTPS atau localhost), dan callback pelacakan yang tidak dihentikan akan terus mengirim posisi selama tab terbuka — selalu simpan id-nya dan panggil clearWatch saat fitur ditutup.

Dengan callback sukses, callback galat, dan tiga opsi pencarian, pemakaian Geolocation API sudah lengkap untuk kasus “toko terdekat” — dan pola dua-jalur ini berulang lagi pada API berizin lainnya yang kita rangkum di chapter berikutnya.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

posisi-pengguna.js

Unduh berkas
javascript
// posisi-pengguna.js — membaca posisi perangkat dengan izin pengguna
// Geolocation API hanya ada di browser;
// berkas ini lolos node --check dan dijalankan pada halaman toko.

const tombolCari = document.querySelector("#cari-toko");
const panelHasil = document.querySelector("#hasil-toko");

tombolCari.addEventListener("click", () => {
  panelHasil.textContent = "Mencari posisi...";

  navigator.geolocation.getCurrentPosition(
    // callback sukses: object GeolocationPosition
    (posisi) => {
      const { latitude, longitude } = posisi.coords;
      console.log(`Posisi: ${latitude.toFixed(4)}, ${longitude.toFixed(4)}`);
      panelHasil.textContent = "Toko terdekat: Cabang Semporna (2,1 km)";
    },
    // callback galat: object GeolocationPositionError
    (error) => {
      console.log("Gagal, kode:", error.code, "-", error.message);
      panelHasil.textContent = "Posisi tidak tersedia. Pilih toko secara manual.";
    },
    { timeout: 8000, maximumAge: 60000, enableHighAccuracy: false }
  );
});