Ders 01 / 20
Tarayıcı ile Farklar
Barındıran ortam kavramı, genel nesnenin içeriği, iki modül sisteminin bir arada bulunması ve sunucu çalışma zamanının yetenek sınırları.
İçindekiler
Eşzamansız JavaScript ve Çalışma Zamanı kursu, tek iş parçacıklı yürütme modelini ve olay döngüsünü kurdu. Orada anlatılan her şey dilin kendisine değil, dili barındıran ortama aitti: görev kuyruğu da, zamanlayıcılar da dil standardında tanımlı değildir. Bu kurs aynı dili farklı bir barındıran ortamda ele alır.
Soru şudur: aynı sözdizim, aynı değer modeli ve aynı olay döngüsü kavramı, tarayıcı yerine bir sunucu sürecinde çalıştığında ne değişir? Yanıt iki başlıkta toplanır — hangi adların hazır bulunduğu ve sürecin ne yapmaya yetkili olduğu.
Dil Çekirdeği ve Barındıran Ortam
Dil standardı, sözdizimi ve değer modelini tanımlar: Array, Map, Promise,
JSON, Math bu katmandadır. Standart, bu değerlerin nasıl davranacağını söyler;
onlarla dış dünyaya nasıl erişileceğini söylemez.
Barındıran ortam (host environment), dili çalıştıran programdır ve dış dünyayla teması o sağlar. Tarayıcı bir barındıran ortamdır: belge ağacını, çerezleri, ekran olaylarını sunar. Sunucu çalışma zamanı da bir barındıran ortamdır: dosya sistemini, süreç bilgisini, ağ dinlemeyi sunar.
Ayrım şöyle sınanabilir. Aşağıdaki dosya, bir dizi adın genel nesnede bulunup bulunmadığını yazar:
// ortam.mjs const adlar = [ 'window', 'document', 'localStorage', 'alert', 'process', 'Buffer', 'global', 'fetch', 'URL', 'TextEncoder', 'AbortController', 'structuredClone', ]; for (const ad of adlar) { console.log(`${ad.padEnd(16)} ${ad in globalThis ? 'var' : 'yok'}`); }
node ortam.mjs
window yok document yok localStorage yok alert yok process var Buffer var global var fetch var URL var TextEncoder var AbortController var structuredClone var
Çıktı üç öbek gösterir. Birinci öbek yalnızca tarayıcıda bulunur: belge ağacı, sayfa
deposu ve kullanıcı arayüzü çağrıları sunucuda karşılıksızdır. İkinci öbek yalnızca
sunucu tarafında bulunur: process süreç bilgisini, Buffer ham baytları temsil eder.
Üçüncü öbek daha ilginçtir. fetch, URL, TextEncoder, AbortController ve
structuredClone tarayıcı için tanımlanmış arayüzlerdir, ancak dile değil web
platformuna aittir. Sunucu çalışma zamanı bunların bir bölümünü aynı sözleşmeyle
gerçekleştirir; böylece iki ortamda çalışan kod yazmak, her arayüzün iki ayrı
sürümünü tutmayı gerektirmez. Bu ortaklık genişleyen bir kümedir: bir arayüzün
belirli bir sürümden itibaren bulunduğu belgelendirilmişse ona güvenilebilir,
bulunmadığı ortamlar için ise varlık denetimi yapılır.
global adı, globalThis ile aynı nesneyi gösteren eski bir addır. Yeni kodda
globalThis yazmak, aynı ifadenin her iki ortamda da çalışmasını sağlar.
İki Modül Sistemi
Tarayıcıda tek bir modül biçimi vardır. Sunucu çalışma zamanı ise iki biçimi bir arada taşır ve her dosya için birini seçer.
CommonJS, require çağrısıyla eşzamanlı yükleme yapan, module.exports nesnesine
yazarak dışa aktaran biçimdir. ES modülleri, import ve export bildirimleriyle
çalışan, bağımlılıkları çalıştırmadan önce çözen biçimdir. İkisinin farkı Modüller,
Araçlar ve Ekosistem kursunda ayrıntılandırılmıştı; burada önemli olan, seçimin nasıl
yapıldığıdır.
Seçim iki kurala bakar: dosya uzantısı ve en yakın paket bildirimi. .cjs uzantılı
dosya her zaman CommonJS, .mjs uzantılı dosya her zaman ES modülüdür. .js
uzantısında karar, dosyanın bulunduğu dizinden yukarı doğru bulunan ilk
package.json dosyasındaki type alanına göre verilir; alan module ise ES modülü,
commonjs ise veya alan yoksa CommonJS.
İki biçimin çalışma anındaki farkı ölçülebilir:
// kapsam.cjs console.log('this === module.exports :', this === module.exports); console.log('__filename son parca :', __filename.split('/').pop()); console.log('require turu :', typeof require);
// kapsam.mjs console.log('this :', this); console.log('import.meta.url son parca:', import.meta.url.split('/').pop()); console.log('require turu :', typeof require);
node kapsam.cjs
this === module.exports : true __filename son parca : kapsam.cjs require turu : function
node kapsam.mjs
this : undefined import.meta.url son parca: kapsam.mjs require turu : undefined
CommonJS dosyası bir fonksiyon gövdesi gibi sarmalanır: require, module,
__filename ve __dirname adları o sarmalayıcının parametreleridir, genel değildir.
ES modülünde bu adlar yoktur; dosyanın kendi konumu import.meta.url üzerinden, bir
dosya yolu olarak değil bir adres olarak verilir. Kurs boyunca ES modülleri
kullanılacak; CommonJS yalnızca farkın görülmesi gereken yerlerde geçecek.
Yetenek ve Yetki
Asıl fark ad listesinde değil, sürecin ne yapabildiğindedir.
Tarayıcıda çalışan kod, kullanıcının makinesine karşı düşman kabul edilir ve bir kum havuzunda tutulur: keyfi bir dosyayı okuyamaz, keyfi bir bağlantı noktasını dinleyemez, başka bir kaynağa isteği ancak o kaynağın izin verdiği ölçüde atabilir. Bu kısıtlar tarayıcının kullanıcıya verdiği güvencelerdir.
Sunucu çalışma zamanında böyle bir kum havuzu yoktur. Süreç, onu başlatan kullanıcının yetkileriyle çalışır. Linux’a Giriş kursunda kurulan izin modeli burada doğrudan geçerlidir: süreç hangi dosyaları okuyabiliyorsa çalıştırdığınız betik de onları okuyabilir. Aynı kural yazma ve silme için de geçerlidir.
Bu yetki, aşağıdaki kısa dosyada görülür:
// ilk-okuma.mjs import { readFileSync } from 'node:fs'; const metin = readFileSync('olcumler.ndjson', 'utf8'); const satirlar = metin.trim().split('\n'); console.log('satir sayisi:', satirlar.length); console.log('ilk kayit :', JSON.parse(satirlar[0]));
Modül adındaki node: öneki, adın bir yerleşik modülü gösterdiğini bildirir. Önek
olmadan da çözümlenir; önekli yazım, aynı adda bir dosya veya paket bulunması
durumunda hangisinin kastedildiğini kesinleştirir. Kurs boyunca önekli biçim
kullanılacak.
Kursun Çalışma Dosyası
Bu kurs boyunca tek bir somut iş geliştirilecek: uzaktaki ölçüm düğümlerinden gelen
kayıtları toplayan, özetleyen ve HTTP üzerinden sunan küçük bir hizmet. Girdi, her
satırı bağımsız bir JSON nesnesi olan bir metin dosyasıdır. Aşağıdaki on iki satırı
olcumler.ndjson adıyla kaydedin:
{"zaman":"2024-02-07T09:12:44Z","dugum":"kenar-01","metrik":"sicaklik","deger":21.4}
{"zaman":"2024-02-07T09:12:44Z","dugum":"kenar-01","metrik":"nem","deger":48.0}
{"zaman":"2024-02-07T09:13:02Z","dugum":"kenar-02","metrik":"sicaklik","deger":19.8}
{"zaman":"2024-02-07T09:13:02Z","dugum":"kenar-02","metrik":"nem","deger":52.5}
{"zaman":"2024-02-07T09:14:19Z","dugum":"kenar-01","metrik":"sicaklik","deger":21.9}
{"zaman":"2024-02-07T09:14:19Z","dugum":"kenar-03","metrik":"sicaklik","deger":24.1}
{"zaman":"2024-02-07T09:15:30Z","dugum":"kenar-02","metrik":"sicaklik","deger":20.2}
{"zaman":"2024-02-07T09:15:30Z","dugum":"kenar-03","metrik":"nem","deger":41.3}
{"zaman":"2024-02-07T09:16:04Z","dugum":"kenar-01","metrik":"nem","deger":47.2}
{"zaman":"2024-02-07T09:16:04Z","dugum":"kenar-03","metrik":"sicaklik","deger":24.6}
{"zaman":"2024-02-07T09:17:22Z","dugum":"kenar-02","metrik":"sicaklik","deger":20.7}
{"zaman":"2024-02-07T09:17:22Z","dugum":"kenar-01","metrik":"sicaklik","deger":22.3}
Her satırdaki dört alan sırasıyla ölçüm anını, ölçümü gönderen düğümü, ölçülen büyüklüğü ve değeri taşır. Satır başına bir kayıt tutan bu biçim, Kabuk Programlama kursundaki satır tabanlı süzgeçlerle uyumludur: dosyanın tamamını belleğe almadan, satır satır işlenebilir. Bu özellik akışlar konusunda belirleyici olacak.
Dosyayı yerine koyduktan sonra ilk okumayı çalıştırın:
node ilk-okuma.mjs
satir sayisi: 12
ilk kayit : {
zaman: '2024-02-07T09:12:44Z',
dugum: 'kenar-01',
metrik: 'sicaklik',
deger: 21.4
}
Bu çıktı, tarayıcıda karşılığı olmayan bir işi gösterir: yerel bir dosya, kullanıcı onayı olmadan, adı verilerek okundu. Kursun geri kalanı bu yeteneğin üzerine kurulur — ve aynı yeteneğin getirdiği sorumluluğu da işler.
Dosya bulunamadığında ortaya çıkan hata, kurs boyunca sık göreceğiniz biçimdedir:
node -e "import('node:fs').then(m => m.readFileSync('yok.ndjson','utf8')).catch(e => console.log(e.code, '|', e.syscall, '|', e.path))"
ENOENT | open | yok.ndjson
ENOENT, işletim sisteminin sistem çağrısından döndürdüğü hata adıdır; syscall
hangi çağrının başarısız olduğunu, path hangi yol için olduğunu söyler. Bu üç alan,
hata iletisinin metnine bakmadan karar vermenizi sağlar — hata metni değişebilir,
kod değişmez.
Özet
- Dil standardı değer modelini tanımlar; dış dünyaya erişim barındıran ortamın sorumluluğudur. Tarayıcı ve sunucu çalışma zamanı iki ayrı barındıran ortamdır.
- Genel nesnede üç öbek vardır: yalnızca tarayıcıda bulunanlar, yalnızca sunucuda bulunanlar ve web platformundan devralınan ortak arayüzler.
- Modül biçimi dosya uzantısıyla (
.cjs,.mjs) veya en yakın paket bildirimindekitypealanıyla seçilir; CommonJS dosyası sarmalanır verequire,module,__filenameadlarını parametre olarak alır. - Sunucu sürecinde kum havuzu yoktur; süreç, kendisini başlatan kullanıcının dosya ve ağ yetkileriyle çalışır.
- Yerleşik modüller
node:önekiyle yazıldığında ad çakışması olasılığı ortadan kalkar; dosya sistemi hatalarıcode,syscallvepathalanlarıyla ayırt edilir.
Sonraki Adım
Bu derste dosya readFileSync ile, yani süreci bekleterek okundu. Tek iş parçacıklı
bir sunucuda bekletmenin bedeli ağırdır: bekleyen süre boyunca başka hiçbir istek
işlenemez. Sonraki ders, bu bedeli ödememek için kullanılan düzeneği aşama aşama
açar — olay döngüsünün hangi sırayla hangi kuyruğu boşalttığını, zamanlayıcıların ne
zaman çalıştığını ve girdi/çıktı geri çağrılarının bu sıraya nereden girdiğini
ölçülebilir örneklerle gösterir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.