Mundarija (38)
- Bu darsda
- 1. Nega bu kerak?
- 2. Ruxsat qanday ishlaydi
- 2.1 Uch holat
- 2.2 navigator.permissions.query: so'ramasdan bilish
- 2.3 Nomlar va xatolar
- 2.4 Bu darsdagi jonli oynalarda ruxsatlar yopiq
- 3. Bildirishnomalar: Notifications API
- 3.1 Ruxsat so'rash
- 3.2 Bildirishnoma ko'rsatish
- 3.3 Cheklovlar
- 4. Joylashuv: Geolocation API
- 4.1 getCurrentPosition
- 4.2 Promise'ga o'rash
- 4.3 Uch xato kodi
- 4.4 Xatolarni to'g'ri ishlash — jonli
- 4.5 watchPosition: harakatni kuzatish
- 4.6 DevTools'da joylashuvni soxtalashtirish
- 5. Qachon va qanday so'rash
- 5.1 Ochilishi bilan so'ramang
- 5.2 To'g'ri naqsh: avval tushuntirish
- 5.3 Holatga qarab interfeys
- 5.4 Yangi yo'l: <geolocation> elementi
- 6. Hujumchi nigohi
- 7. Ko'p uchraydigan xatolar
- 7.1 Sahifa ochilishi bilan so'rash
- 7.2 Xato callback'isiz getCurrentPosition
- 7.3 timeout siz
- 7.4 "default" va "prompt" ni aralashtirish
- 7.5 clearWatch siz
- 8. Mashqlar
- 1-mashq (oson): Bildirishnoma holati
- 2-mashq (o'rta): Ruxsatdan oldin tushuntirish
- 3-mashq (qiyin): «Bahor»gacha masofa
- 4-mashq: Amaliy tajriba — vazifalar eslatmasi
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript Permissions, Notifications va Geolocation: ruxsat so'raydigan API'lar
Qisqacha: Joylashuv, bildirishnoma, kamera kabi API'lar foydalanuvchidan ruxsat so'raydi.
navigator.permissions.query({ name: "geolocation" })ruxsat holatini (granted,denied,prompt) so'ramasdan bilib beradi.Notification.requestPermission()vanavigator.geolocation.getCurrentPosition()esa ruxsat oynasini chiqaradi. Qoida: ruxsatni sahifa ochilishi bilan emas, foydalanuvchi o'sha imkoniyatni so'raganda va sababini tushuntirib so'rang.
Bu darsda
- Ruxsat holatlarini (
prompt,granted,denied) va ular qanday o'zgarishini tushuntira olasiz. navigator.permissions.querybilan holatni bilib, interfeysni unga moslaysiz.Notification.requestPermissionvanew Notificationbilan bildirishnoma ko'rsatasiz.getCurrentPositionvawatchPositionbilan joylashuv olasiz, uch xato kodini to'g'ri ishlaysiz.- Ruxsatni "to'g'ri vaqtda, to'g'ri gap bilan" so'rash UX'ini qo'llaysiz.
Oldin bilishingiz kerak: Clipboard va Web Share API, Promise asoslari, async / await, Callback'lar.
1. Nega bu kerak?
O'tgan darsda ko'rdik: buferni o'qish uchun brauzer ruxsat so'raydi. Bunday API'lar ko'p. Telefoningizni eslang: yangi ilova "Joylashuvingizni ko'rishga ruxsat berasizmi?", "Bildirishnoma yuborishga ruxsat berasizmi?" deb so'raydi. Brauzer ham xuddi shunday.
«Bahor»da ikki yangi g'oya bor:
- "Eng yaqin filial" tugmasi. Mehmonning joylashuvini olib, unga yaqin filialni ko'rsatish — Geolocation API.
- "Buyurtma tayyor" xabari. Mehmon boshqa tabda o'tirgan bo'lsa ham, taomi tayyor bo'lganda ekran burchagida xabar chiqsin — Notifications API.
Ikkalasi ham shaxsiy narsaga tegadi: qayerda ekaningiz va diqqatingiz. Shuning uchun brauzer ularni ruxsatsiz bermaydi. Bu darsda ruxsat bilan ishlashni o'rganamiz: qanday so'rash, qanday tekshirish va "yo'q" javobini qanday hurmat qilish.
2. Ruxsat qanday ishlaydi
2.1 Uch holat
Har bir ruxsat — har sayt uchun alohida saqlanadigan qaror. Uning uch holati bor:
stateDiagram-v2
[*] --> prompt: sayt birinchi marta
prompt --> granted: "Ruxsat berish"
prompt --> denied: "Bloklash"
granted --> prompt: sozlamalarda tiklash
denied --> prompt: sozlamalarda tiklashprompt— hali so'ralmagan. API chaqirilsa, brauzer ruxsat oynasini ko'rsatadi.granted— ruxsat berilgan. Oyna chiqmaydi, API darhol ishlaydi.denied— rad etilgan. Oyna endi chiqmaydi, API darhol xato beradi.
Oxirgi nuqta muhim. Foydalanuvchi bir marta "Bloklash" ni bossa, sayt uni qayta so'ray olmaydi. Faqat foydalanuvchining o'zi manzil satridagi qulf belgisi orqali sozlamani tiklaydi. Shuning uchun birinchi so'rov — yagona imkoniyat. Uni isrof qilmang.
2.2 navigator.permissions.query: so'ramasdan bilish
Ruxsat holatini bilish uchun Permissions API bor. U ruxsat oynasini chiqarmaydi — faqat "hozir qaysi holat?" deb javob beradi:
const status = await navigator.permissions.query({
name: "geolocation",
});
console.log(status.state); // "prompt", "granted" yoki "denied"Javob — PermissionStatus obyekti. Unda state (holat), name (ruxsat nomi) va change hodisasi bor. Foydalanuvchi sozlamalarda ruxsatni o'zgartirsa, sahifa buni darhol biladi:
status.addEventListener("change", () => {
console.log(`Joylashuv ruxsati endi: ${status.state}`);
});Biz Live Server sahifasida (Chrome 154) sinadik: ruxsat berilgan sahifada query → granted, keyin ruxsatni olib tashlaganimizda change hodisasi keldi va state prompt ga qaytdi.
2.3 Nomlar va xatolar
name — qat'iy ro'yxatdan: "geolocation", "notifications", "camera", "microphone", "clipboard-read", "clipboard-write", "persistent-storage", "screen-wake-lock" va boshqalar. Ro'yxatda yo'q nom bersangiz:
TypeError: Failed to execute 'query' on 'Permissions': Failed to read the 'name' property from 'PermissionDescriptor': The provided value 'clipboard' is not a valid enum value of type PermissionName.Tarjimasi: "'clipboard' qiymati PermissionName turining ruxsat etilgan qiymatlaridan biri emas". Ya'ni nom xato — "clipboard-read" yoki "clipboard-write" kerak edi. Bu ro'yxat brauzerlarda farq qiladi: bir brauzer taniydigan nomni boshqasi tanimasligi va xuddi shunday TypeError berishi mumkin (MDN'dagi brauzerlar jadvaliga qarang). Shuning uchun query ni har doim try/catch ichida chaqiring.
Diqqat: Permissions API faqat o'qiydi. "Ruxsat so'ra" degan metodi yo'q. Ruxsat oynasini API'ning o'zi chiqaradi:
getCurrentPosition,Notification.requestPermission,readText.
2.4 Bu darsdagi jonli oynalarda ruxsatlar yopiq
Jonli oyna — sayt ichidagi alohida, ajratilgan sahifa. Sayt unga ruxsatlar siyosati (permissions policy) bilan imkoniyatlarni cheklaydi: bufer yozish bor, joylashuv, kamera va bildirishnoma — yo'q. Ko'ring:
<script type="module">
const names = [
"geolocation",
"notifications",
"camera",
"clipboard-write",
];
for (const name of names) {
const status = await navigator.permissions.query({ name });
console.log(`${name}: ${status.state}`);
}
</script>Konsolda:
geolocation: denied
notifications: denied
camera: denied
clipboard-write: grantedUch API darhol denied — ruxsat oynasi chiqmaydi ham. Bu sizning brauzeringiz sozlamasi emas: oyna siyosat bo'yicha yopiq. Shu sabab joylashuv va bildirishnoma misollarini Live Server'da sinaysiz. Darsdagi ularning natijalari — Live Server sahifasida, Chrome 154 da olingan: ruxsat oldindan berildi, joylashuv esa soxtalashtirildi. O'zingiz ham shunday qila olasiz: DevTools → ⋮ → More tools → Sensors → Location — istalgan koordinatani yoki «Location unavailable» ni tanlang.
Tekshirib ko'ring: Foydalanuvchi joylashuv so'roviga "Bloklash" ni bosdi. Ertasi kuni sayt yana
getCurrentPositionni chaqirdi. Ruxsat oynasi chiqadimi?
Javob
Yo'q. Holat denied — brauzer qarorni eslab qolgan va API darhol xato beradi (code 1). Foydalanuvchi qulf belgisi orqali sozlamani o'zi tiklamaguncha, sayt qayta so'ray olmaydi. Shuning uchun birinchi so'rovni to'g'ri vaqtda qilish muhim.
3. Bildirishnomalar: Notifications API
3.1 Ruxsat so'rash
Bildirishnoma (notification) — operatsion tizimning xabar oynasi: ekran burchagida chiqadi, brauzer boshqa tabda yoki kichraytirilgan bo'lsa ham ko'rinadi. Avval ruxsat:
const result = await Notification.requestPermission();
console.log(result); // "granted", "denied" yoki "default"Notification.requestPermission() — ruxsat oynasini chiqaradi va Promise qaytaradi. Javob — foydalanuvchi tanlovi.
Nomlardagi farqqa e'tibor bering. Bildirishnomaning o'z xususiyati Notification.permission va requestPermission "hali so'ralmagan" holatni "default" deb ataydi. Permissions API esa xuddi shu holatni "prompt" deydi. Ma'nosi bir xil — tarixan ikki API turli vaqtda yozilgan.
Live Server sahifasida sinadik: ruxsat berilmagan headless (oynasiz, avtomatik sinov uchun) Chrome'da so'rov darhol denied bilan tugadi — u yerda ruxsat oynasini bosadigan odam yo'q. Haqiqiy brauzerda ruxsat oynasi chiqadi va javob foydalanuvchi tanloviga bog'liq.
3.2 Bildirishnoma ko'rsatish
if (Notification.permission === "granted") {
const note = new Notification("«Bahor»: buyurtma tayyor", {
body: "Osh — 2 porsiya. Kassaga yaqinlashing.",
tag: "buyurtma-12",
});
note.addEventListener("click", () => {
window.focus(); // saytning tabiga qaytish
note.close();
});
}- Birinchi argument — sarlavha.
body— asosiy matn. tag— "bu qaysi xabar". Bir xiltagli yangi bildirishnoma eskisining o'rnini egallaydi. Buyurtma holati uch marta o'zgarsa ("qabul qilindi", "tayyorlanmoqda", "tayyor"), ekranda uchta emas, bitta xabar turadi.clickhodisasi — foydalanuvchi xabarni bosdi. Odatda saytga qaytaramiz va xabarni yopamiz.icon— kichik rasm manzili; sayt logotipi uchun.
Ruxsat berib sinadik: show hodisasi keldi va xabarda biz bergan sarlavha, matn va tag bor edi. note.close() dan keyin close hodisasi keldi.
3.3 Cheklovlar
- Faqat sahifa ochiq turganda.
new Notification— sahifa yopilsa, bildirishnoma yuborib bo'lmaydi. Sayt yopiq bo'lsa ham kelsa — bu Push bildirishnoma, uning uchun Service Worker kerak. Service Worker — sahifadan alohida, fonda ishlaydigan skript; uni Service Worker hayot sikli darsida, Push'ni PWA darsida ko'ramiz. - Android Chrome'da
new Notificationishlamaydi — u yerda faqat Service Worker orqali (registration.showNotification). Shuning uchun Notifications API web-features'da hali "Baseline" emas (2026-oktabr). - Xavfsiz kontekst. HTTP sahifada
Notification.permissiondoim"denied"(bizhttp://bahor.testda tekshirdik). - Iframe ichida so'rab bo'lmaydi. Chrome boshqa domendan joylashtirilgan iframe'ga bildirishnoma ruxsatini so'ratmaydi — reklama oynalari foydalanuvchini bezor qilmasin.
Tekshirib ko'ring: Buyurtma holati besh marta o'zgaradi va har safar bildirishnoma yuboriladi. Foydalanuvchi ekranida beshta xabar to'planib qolmasligi uchun nima qilasiz?
Javob
Hamma xabarlarga bir xil tag bering (masalan, "buyurtma-12"). Bir xil tag li yangi bildirishnoma eskisining o'rnini egallaydi — ekranda doim bitta, eng yangi holat turadi.
4. Joylashuv: Geolocation API
4.1 getCurrentPosition
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude, accuracy } = position.coords;
console.log(latitude, longitude, `±${accuracy} m`);
},
(error) => {
console.log(`Xato ${error.code}: ${error.message}`);
},
);Bu API Promise'dan oldin yozilgan, shuning uchun ikki callback oladi: muvaffaqiyat va xato. Callback'lar darsidagi uslub. Birinchi chaqiruvda ruxsat oynasi chiqadi.
Live Server'da, joylashuv (Sensors orqali) Toshkent markaziga qo'yilganda (latitude: 41.3111, longitude: 69.2797, aniqlik 25 m), muvaffaqiyat callback'iga shunday obyekt keldi:
{
timestamp: 1791223235420,
coords: {
accuracy: 25,
latitude: 41.3111,
longitude: 69.2797,
altitude: null,
altitudeAccuracy: null,
heading: null,
speed: null
}
}latitude— kenglik (shimol-janub, −90…90),longitude— uzoqlik (g'arb-sharq, −180…180). Xaritadagi nuqta shu ikki son.accuracy— aniqlik, metrda: haqiqiy joy shu radius ichida. GPS'da 5–20 m, faqat Wi-Fi bo'yicha — yuzlab metr, IP bo'yicha — kilometrlar.altitude(balandlik),speed(tezlik),heading(yo'nalish) — qurilma bilsagina; kompyuterda odatdanull.timestamp— o'lchangan vaqt (millisoniya,Date.now()kabi).
4.2 Promise'ga o'rash
await bilan yozish qulayroq. Promise asoslari darsidagi usul — callback'li funksiyani new Promise ga o'rash:
function getPosition(options) {
return new Promise((resolve, reject) => {
const geo = navigator.geolocation;
geo.getCurrentPosition(resolve, reject, options);
});
}
const position = await getPosition({ timeout: 10000 });Uchinchi argument — sozlamalar:
| Sozlama | Ma'nosi | Sukut |
|---|---|---|
enableHighAccuracy |
GPS'ni yoqib, aniqroq o'lchash (batareyani ko'proq yeydi) | false |
timeout |
ko'pi bilan necha ms kutish | cheksiz |
maximumAge |
necha ms gacha eski (keshdagi) javob ham bo'ladi | 0 |
timeout siz chaqiruv cheksiz kutishi mumkin — masalan, binoning ichida GPS signal topolmasa. Doim timeout bering.
4.3 Uch xato kodi
Xato callback'iga GeolocationPositionError keladi. Uning code i uch qiymatdan biri:
code |
Nomi | Qachon |
|---|---|---|
| 1 | PERMISSION_DENIED |
ruxsat yo'q yoki siyosat yopgan |
| 2 | POSITION_UNAVAILABLE |
qurilma joyni aniqlay olmadi |
| 3 | TIMEOUT |
timeout ichida javob kelmadi |
Uchalasini ham Chrome 154 da oldik:
- Ruxsat rad etilganda:
code1,User denied Geolocation. HTTP sahifada:code1,Only secure origins are allowed (see: https://goo.gl/Y0ZkNV).— "faqat xavfsiz manbalarga ruxsat". - Joy aniqlanmaganda (Sensors'da «Location unavailable»):
code2,message— bo'sh satr. { timeout: 0 }bilan:code3,Timeout expired.
Ikkinchi holatdagi bo'sh message — muhim saboq: message brauzerga bog'liq, foydalanuvchiga ko'rsatish uchun emas. Matnni code ga qarab o'zingiz yozing.
4.4 Xatolarni to'g'ri ishlash — jonli
Bu jonli oynada joylashuv siyosat bo'yicha yopiq. Bu ham foydali: xato yo'lini ko'rasiz.
<style>
body { font: 1rem/1.5 system-ui, sans-serif; margin: 1rem; }
button { font: inherit; padding: 0.4rem 0.8rem; }
#result { min-height: 1.5em; }
</style>
<button id="nearest" type="button">Eng yaqin filial</button>
<p id="result" role="status"></p>
<script>
const MESSAGES = {
1: "Joylashuvga ruxsat yo'q. Filialni ro'yxatdan tanlang.",
2: "Joyingizni aniqlab bo'lmadi. Keyinroq urinib ko'ring.",
3: "Javob kelmadi. Internet yoki GPS'ni tekshiring.",
};
const result = document.getElementById("result");
document.getElementById("nearest").addEventListener("click", () => {
result.textContent = "Joylashuv aniqlanmoqda…";
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
result.textContent = `Siz: ${latitude}, ${longitude}`;
},
(error) => {
result.textContent = MESSAGES[error.code];
console.log(`xato kodi: ${error.code}`);
console.log(error.message);
},
{ timeout: 10000 },
);
});
</script>«Eng yaqin filial» ni bosing. Konsolda (Live Server'da bosib olingan):
xato kodi: 1
Geolocation has been disabled in this document by permissions policy.Ekranda esa foydalanuvchiga tushunarli matn: Joylashuvga ruxsat yo'q. Filialni ro'yxatdan tanlang. Brauzerning inglizcha message i faqat konsolda — dasturchi uchun.
E'tibor bering: xato bo'lsa ham foydalanuvchiga boshqa yo'l taklif qilinadi — "ro'yxatdan tanlang". Joylashuv — qulaylik, majburiyat emas.
4.5 watchPosition: harakatni kuzatish
Kurer yo'lda, mehmon xaritada uning yaqinlashishini ko'rmoqchi. Bir marta emas, doimiy joylashuv kerak:
const watchId = navigator.geolocation.watchPosition(
(position) => updateMap(position.coords),
(error) => console.log(`Xato ${error.code}`),
{ enableHighAccuracy: true, maximumAge: 5000 },
);
// kuzatuv kerak bo'lmay qolganda:
navigator.geolocation.clearWatch(watchId);watchPosition callback'ni har joy o'zgarganda chaqiradi va son qaytaradi — kuzatuv raqami. Uni clearWatch ga berib to'xtatasiz: setInterval va clearInterval juftligi kabi. Biz sinadik: joylashuvni o'zgartirganimizda callback yangi koordinata bilan keldi, clearWatch dan keyingi o'zgarishda esa — kelmadi.
clearWatch ni unutmang. GPS yoqilgan holda qolsa, telefon batareyasi tez tugaydi.
4.6 DevTools'da joylashuvni soxtalashtirish
Har safar Samarqandga borib sinab bo'lmaydi. DevTools → Ctrl + Shift + P → Show Sensors → Location ro'yxatidan shahar tanlang yoki o'z kenglik/uzoqlikni yozing. "Location unavailable" tanlansa — code 2 xatosini sinaysiz.
Tekshirib ko'ring: Sardor joylashuv xatosida foydalanuvchiga
error.messageni ko'rsatdi. Ikki sababini ayting, nega bu yomon.
Javob
Birinchidan, matn inglizcha va texnik ("permissions policy") — mehmon Dilshod aka tushunmaydi. Ikkinchidan, u brauzerga bog'liq va bo'sh bo'lishi mumkin (code 2 da Chrome bo'sh satr berdi). Foydalanuvchi matnini code bo'yicha o'zingiz yozing, message — faqat konsolga.
5. Qachon va qanday so'rash
5.1 Ochilishi bilan so'ramang
Eng ko'p uchraydigan xato: sahifa ochilishi bilan "Bildirishnomalarga ruxsat bering" oynasi. Dilshod aka hali sayt nima ekanini bilmaydi — u "Bloklash" ni bosadi. Va bu denied — abadiy. Bu muammo shunchalik keng tarqalganki, brauzerlar choralar ko'rdi:
- Firefox 72-versiyadan (2020-yil yanvar) bildirishnoma so'rovini faqat foydalanuvchi harakatidan (bosish, tugma) keyin oyna qilib ko'rsatadi. Harakatsiz so'rovda oyna chiqmaydi — manzil satrida faqat kichik belgi paydo bo'ladi.
- Chrome 80-versiyadan (2020-yil boshi) bildirishnomalar uchun "jimroq" ko'rinishga ega. Oyna o'rniga manzil satrida qisqa "Notifications blocked" yozuvi va ustidan chizilgan qo'ng'iroq belgisi chiqadi. Bu ikki holatda avtomatik yoqiladi: so'rovlarni deyarli hech kim qabul qilmaydigan saytlarda va bildirishnomalarni tez-tez rad etadigan foydalanuvchilarda.
5.2 To'g'ri naqsh: avval tushuntirish
sequenceDiagram
participant M as Mehmon
participant S as Sayt
participant B as Brauzer
M->>S: "Buyurtma berish" ni bosdi
S->>M: "Tayyor bo'lganda xabar beraylikmi?" [Ha] [Yo'q]
M->>S: [Ha]
S->>B: Notification.requestPermission()
B->>M: Ruxsat oynasi
M->>B: Ruxsat berish
B->>S: "granted"Ikki qadam:
- O'z tushuntirishingiz — sayt ichidagi oddiy tugma yoki oyna: nima uchun kerak va foydalanuvchi nima oladi. "Yo'q" desa — hech narsa qilmaysiz,
deniedga tushmaysiz, keyinroq yana taklif qilish mumkin. - Faqat "Ha" dan keyin — brauzer so'rovi. Endi foydalanuvchi nima bo'layotganini biladi va ko'pincha rozi bo'ladi.
5.3 Holatga qarab interfeys
Permissions API shu yerda kerak: tugmani holatga moslash.
async function setupLocationButton(button) {
try {
const status = await navigator.permissions.query({
name: "geolocation",
});
const update = () => {
button.hidden = status.state === "denied";
};
status.addEventListener("change", update);
update();
} catch {
// query qo'llanmasa — tugma ko'rinib turaveradi
}
}denied bo'lsa — tugmani yashiramiz: bosilsa baribir ishlamaydi. O'rniga "Joylashuv o'chirilgan — filialni ro'yxatdan tanlang" kabi matn ko'rsatish ham mumkin. granted bo'lsa — foydalanuvchi allaqachon rozi, joylashuvni bir bosishda olamiz. change tinglovchisi — foydalanuvchi sozlamani o'zgartirsa, tugma ham o'zgaradi.
5.4 Yangi yo'l: <geolocation> elementi
Chrome 144 dan <geolocation> HTML elementi bor — joylashuvni so'raydigan tayyor tugma. Brauzer uni o'zi chizadi va bosish haqiqatan foydalanuvchi niyati ekaniga ishonadi. Shuning uchun denied holatidan ham qayta so'ray oladi. Hozircha faqat Chromium brauzerlarida (web-features, 2026-oktabr) — oddiy tugma bilan zaxira kerak. Bu darsda batafsil to'xtalmaymiz.
6. Hujumchi nigohi
Joylashuv — eng nozik shaxsiy ma'lumotlardan biri. U uyingiz, ishxonangiz va kun tartibingizni ochib beradi.
- Ortiqcha so'rash. Sayt "eng yaqin filial" uchun ruxsat oladi, keyin
watchPositionbilan har 5 soniyada joyni serverga yuboradi — reklama kompaniyasi uchun. Himoya dasturchi tomonida: kerakli paytda, kerakli aniqlikda, bir marta. "Eng yaqin filial" uchungetCurrentPositionyetadi,enableHighAccuracyshart emas. Serverga yuborish shart bo'lsa — koordinatani yaxlitlang (latitude.toFixed(2)— taxminan 1 km). - Begona skript. Sahifaga ulangan har skript (analitika, vidjet) sizning ruxsatingiz bilan ishlaydi: siz ruxsat olgan bo'lsangiz, u ham
getCurrentPositionni chaqira oladi. Shuning uchun ruxsat — butun sayt uchun mas'uliyat. Skriptlarni cheklash — Brauzer xavfsizlik modeli darsida. - Iframe'lar. Joylashtirilgan begona oynaga sukut bo'yicha ruxsatlar berilmaydi — biz buni jonli oynalarda ko'rdik (
denied). Ruxsat kerak bo'lsa, ota sahifaallow="geolocation"bilan aniq beradi. Kerakmasini bermang. - Spam bildirishnomalar. "Videoni ko'rish uchun Ruxsat berish ni bosing" — firibgarlarning eski usuli: keyin reklama xabarlari yog'iladi. Foydalanuvchi sifatida: sababi tushunarsiz so'rovga "Bloklash".
7. Ko'p uchraydigan xatolar
7.1 Sahifa ochilishi bilan so'rash
Yuqorida aytdik: rad etish ehtimoli yuqori va denied — qaytarib bo'lmaydi. Tuzatish: foydalanuvchi o'sha imkoniyatni so'raganda, avval tushuntirib.
7.2 Xato callback'isiz getCurrentPosition
// ❌ ruxsat rad etilsa — hech narsa bo'lmaydi
navigator.geolocation.getCurrentPosition(showOnMap);Ikkinchi argument yo'q — xato jim yutiladi. Foydalanuvchi tugmani bosadi, hech narsa o'zgarmaydi. Tuzatish: doim xato callback'i va foydalanuvchiga matn.
7.3 timeout siz
GPS signal topolmasa — "aniqlanmoqda…" abadiy turadi. Tuzatish: { timeout: 10000 } va code 3 uchun matn.
7.4 "default" va "prompt" ni aralashtirish
Notification.permission === "prompt" — hech qachon true bo'lmaydi: u "default" qaytaradi. Tuzatish: Notification.permission uchun "default", permissions.query uchun "prompt".
7.5 clearWatch siz
Sahifadan ketildi yoki kuzatuv kerak emas — GPS ishlab turibdi. Tuzatish: watchId ni saqlang va kerak bo'lmaganda clearWatch(watchId).
8. Mashqlar
1-mashq (oson): Bildirishnoma holati
Notification.permission ga qarab #note-status ga matn yozing: default — "Bildirishnomalar hali so'ralmagan", granted — "Bildirishnomalar yoqilgan", denied — "Bildirishnomalar bloklangan (brauzer sozlamalaridan yoqing)". Bu jonli oynada uchinchisi chiqishi kerak (Notification.permission siyosat tufayli denied).
Yechim
<p id="note-status"></p>
<script>
const TEXTS = {
default: "Bildirishnomalar hali so'ralmagan",
granted: "Bildirishnomalar yoqilgan",
denied:
"Bildirishnomalar bloklangan (brauzer sozlamalaridan yoqing)",
};
const state = Notification.permission;
document.getElementById("note-status").textContent = TEXTS[state];
console.log(state);
</script>Konsolda:
deniedObyekt kalitlari aynan holat nomlari — if/else zanjiri kerak emas. Live Server'da ochsangiz default (hali so'ralmagan) chiqadi.
2-mashq (o'rta): Ruxsatdan oldin tushuntirish
Live Server'da sahifa yozing: «Buyurtma tayyor bo'lganda xabar beraylikmi?» degan matn va ikki tugma — «Ha» va «Keyinroq». «Ha» bosilganda Notification.requestPermission() chaqirilsin; granted bo'lsa — 3 soniyadan keyin «Bahor»: buyurtma tayyor bildirishnomasi chiqsin (tag: "buyurtma"). «Keyinroq» — taklifni yashirsin, ruxsat so'ramasin. Agar Notification.permission allaqachon denied bo'lsa, taklif umuman ko'rinmasin.
Yechim
<div id="offer" hidden>
<p>Buyurtma tayyor bo'lganda xabar beraylikmi?</p>
<button id="yes" type="button">Ha</button>
<button id="later" type="button">Keyinroq</button>
</div>
<script>
const offer = document.getElementById("offer");
offer.hidden = Notification.permission !== "default";
document.getElementById("later").addEventListener("click", () => {
offer.hidden = true; // ruxsat so'ralmadi, keyin yana taklif
});
const yesButton = document.getElementById("yes");
yesButton.addEventListener("click", async () => {
offer.hidden = true;
const result = await Notification.requestPermission();
console.log(`ruxsat: ${result}`);
if (result !== "granted") return;
setTimeout(() => {
new Notification("«Bahor»: buyurtma tayyor", {
body: "Osh — 2 porsiya",
tag: "buyurtma",
});
}, 3000);
});
</script>Ruxsat berib sinadik: «Ha» → konsolda ruxsat: granted, 3 soniyadan keyin bildirishnomaning show hodisasi keldi. Ruxsat bloklangan bo'lsa — ruxsat: denied va bildirishnoma yo'q. Haqiqiy brauzerda «Ha» dan keyin ruxsat oynasi chiqadi. granted bo'lsa ham taklif ko'rinmaydi — so'raydigan narsa qolmagan.
3-mashq (qiyin): «Bahor»gacha masofa
Mehmon joylashuvini olib, «Bahor»gacha masofani hisoblang. «Bahor» koordinatasi (mashq uchun): 41.3111, 69.2797. Ikki nuqta orasidagi masofa — Haversine formulasi (Yer — radiusi 6 371 km li shar):
const R = 6371000; // Yer radiusi, metr
const toRad = (deg) => (deg * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(dLon / 2) ** 2;
const meters = 2 * R * Math.asin(Math.sqrt(a));Formulani distanceMeters(lat1, lon1, lat2, lon2) funksiyasiga o'rang. Keyin watchPosition bilan kuzating: har yangilanishda #distance ga «Bahor»gacha: 1.2 km (1 000 m dan kam bo'lsa — 850 m) yozilsin. Masofa 100 m dan kam bo'lsa — Yetib keldingiz! va kuzatuv to'xtasin. Xatolar — «Xatolarni to'g'ri ishlash — jonli» bo'limidagi MESSAGES bilan. DevTools Sensors bilan sinang.
Yechim
const BAHOR = { lat: 41.3111, lon: 69.2797 };
const output = document.getElementById("distance");
function distanceMeters(lat1, lon1, lat2, lon2) {
const R = 6371000;
const toRad = (deg) => (deg * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(dLon / 2) ** 2;
return 2 * R * Math.asin(Math.sqrt(a));
}
function formatDistance(m) {
if (m < 1000) return `${Math.round(m)} m`;
return `${(m / 1000).toFixed(1)} km`;
}
const watchId = navigator.geolocation.watchPosition(
({ coords }) => {
const m = distanceMeters(
coords.latitude, coords.longitude, BAHOR.lat, BAHOR.lon,
);
if (m < 100) {
output.textContent = "Yetib keldingiz!";
navigator.geolocation.clearWatch(watchId);
return;
}
output.textContent = `«Bahor»gacha: ${formatDistance(m)}`;
},
(error) => (output.textContent = MESSAGES[error.code]),
{ timeout: 10000 },
);Yechim sahifada <p id="distance" role="status"></p> borligini va MESSAGES obyekti jonli misoldan shu faylga ko'chirilganini nazarda tutadi. Ularsiz kod ishlamaydi: output — null, MESSAGES esa ReferenceError beradi.
Joylashuvni uch marta o'zgartirib sinadik: 41.3200, 69.2500 da — «Bahor»gacha: 2.7 km, 41.3150, 69.2797 da — «Bahor»gacha: 434 m, 41.3115, 69.2797 da — Yetib keldingiz!, undan keyingi o'zgarish esa matnni o'zgartirmadi (kuzatuv to'xtagan).
Nega aynan Haversine? Yer yassi emas: kenglik va uzoqlik graduslari turli joyda turli metrga teng (Toshkentda 1° uzoqlik ≈ 84 km, ekvatorda ≈ 111 km). Shahar ichidagi masofa uchun bu formula yetarlicha aniq. Yo'l bo'ylab masofa (ko'chalar) — xarita xizmatlari (Yandex, Google) ishi.
4-mashq: Amaliy tajriba — vazifalar eslatmasi
Kanon kodga tegmasdan tajriba: kurs/mashqlar/13/07-eslatma/index.html — Live Server'da ochiladigan kichik sahifa. Maydon va «Eslatma qo'yish» tugmasi: vazifa matni va soniyalar soni (5–60). Bosilganda:
Notification.permissiondefaultbo'lsa — tugma ostida bir gap bilan sababini yozing varequestPermission()chaqiring.grantedbo'lsa — belgilangan soniyadan keyinEslatma: <matn>bildirishnomasi,tag— vazifa matni (bir vazifaga ikki eslatma bir-birini almashtirsin).deniedbo'lsa — bildirishnoma o'rniga sahifadagirole="status"maydonida eslatma chiqsin.- Bildirishnoma bosilsa —
window.focus().
Permissions API bilan sahifa ochilganda holatni ko'rsating va change da yangilang.
Yechim
<label for="task">Vazifa:</label>
<input id="task" value="Bron ro'yxatini tekshirish">
<label for="seconds">Necha soniyadan keyin:</label>
<input id="seconds" type="number" min="5" max="60" value="5">
<button id="remind" type="button">Eslatma qo'yish</button>
<p id="state"></p>
<p id="fallback" role="status"></p>
<script type="module">
const stateText = document.getElementById("state");
const fallback = document.getElementById("fallback");
try {
const status = await navigator.permissions.query({
name: "notifications",
});
const show = () => {
stateText.textContent = `Ruxsat: ${status.state}`;
};
status.addEventListener("change", show);
show();
} catch {
stateText.textContent = "Ruxsat holatini bilib bo'lmadi";
}
function remind(text) {
if (Notification.permission === "granted") {
const title = `Eslatma: ${text}`;
const note = new Notification(title, { tag: text });
note.addEventListener("click", () => window.focus());
} else {
fallback.textContent = `Eslatma: ${text}`;
}
}
const remindButton = document.getElementById("remind");
remindButton.addEventListener("click", async () => {
const text = document.getElementById("task").value.trim();
const seconds = Number(document.getElementById("seconds").value);
if (Notification.permission === "default") {
fallback.textContent = "Eslatmani ekran burchagida ko'rsatish "
+ "uchun brauzer ruxsat so'raydi.";
await Notification.requestPermission();
}
setTimeout(() => remind(text), seconds * 1000);
});
</script>Ruxsat berib va bermay sinab ko'ring. denied holatida ham eslatma yo'qolmaydi — sahifaning o'zida chiqadi. Sinash uchun ruxsatni manzil satridagi belgi → "Reset permission" bilan tiklang — Ruxsat: yozuvi change orqali o'zi yangilanadi.
git add 13/07-eslatma/index.html
git commit -m "13/07: bildirishnoma eslatmasi tajribasi"9. Real ishda
- Xarita va yetkazib berish — Yandex Go, Uzum Tezkor, Express24: veb versiyalarda "Joylashuvimni aniqlash" tugmasi
getCurrentPosition, kurer kuzatuvi —watchPositionyoki serverdan keladigan koordinatalar. - Bildirishnomalar — Gmail, Telegram Web, Slack: yangi xabar kelganda. Ko'pchiligi Push (Service Worker) ishlatadi — tab yopiq bo'lsa ham keladi.
- Ruxsat UX'i — katta kompaniyalar ruxsat so'rovidan oldin o'z tushuntirish oynasini ko'rsatadi ("soft ask"). Bu rozilik foizini sezilarli oshiradi.
- Huquqiy tomon — joylashuv shaxsiy ma'lumot. Ko'p mamlakatlarda (Yevropada GDPR, O'zbekistonda "Shaxsga doir ma'lumotlar to'g'risida"gi qonun) uni yig'ish va saqlash qoidalari bor.
- Intervyu. "Permissions API nima qila oladi va nima qila olmaydi?", "Geolocation xato kodlari?", "Bildirishnoma ruxsatini qachon so'raysiz?" — frontend intervyularida uchraydi.
Xulosa
- Ruxsat — har sayt uchun saqlanadigan qaror:
prompt→granted/denied;denieddan sayt o'zi qaytara olmaydi. navigator.permissions.query({ name })— holatni o'qiydi vachangehodisasini beradi; so'ramaydi.Notification.requestPermission()→"granted" | "denied" | "default";new Notification(sarlavha, { body, tag })— sahifa ochiq turganda.getCurrentPosition(ok, xato, { timeout })vawatchPosition/clearWatch; xato kodlari 1, 2, 3 — foydalanuvchi matninicodebo'yicha yozing.- So'rovni foydalanuvchi harakatida va o'z tushuntirishingizdan keyin qiling; har doim ruxsatsiz zaxira yo'li bo'lsin.
Keyingi dars: navigator va qurilma API'lari — tarmoq holati, til, to'liq ekran, ekran qulfi va "qaysi brauzer?" o'rniga "bu imkoniyat bormi?" deb so'rash.
Manbalar
- W3C: "Permissions" — w3c.github.io/permissions
- WHATWG: "Notifications API Standard" — notifications.spec.whatwg.org
- W3C: "Geolocation" — w3c.github.io/geolocation
- MDN:
Permissions.query(),Notification,Geolocation— developer.mozilla.org - web.dev: "Permission UX" va "Best practices for notifications" — web.dev
- Mozilla: "Restricting Notification Permission Prompts in Firefox" (2019-yil 4-noyabr, Firefox 72) — blog.mozilla.org
- Chromium Blog: "Introducing quieter permission UI for notifications" (2020-yil 7-yanvar, Chrome 80) — blog.chromium.org
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!