Node.js'te kullanıcıdan girdi almak için process.stdin üzerinde bir readline arayüzü oluştur ve rl.question() ile sor. Node.js'te prompt() yoktur: tarayıcıdaki sürümü bir diyalog açar, terminal programında ise diyalog yoktur. Modern yol readline/promises kullanır; orada await rl.question('Name? ') kullanıcının yazdığı satırı döndürür. İşin bitince arayüzü kapat, yoksa program daha fazla girdi beklemeye devam eder.
question() sorusunu yazdırdı, bir satır girdi bekledi ve onu satır sonu olmadan döndürdü, bu yüzden program Next year you will be 37. yazdırdı. Birden fazla soru için question() çağrılarını birbiri ardına await et.
Callback ile readline question()
Her Node.js sürümünde bulunan orijinal API, cevabı bir callback'e geçirir. İç içe sorular iç içe callback'ler demektir:
Program soruyu, ardından You picked blue. yazdırdı. Cevap düz bir string'dir, bu yüzden karşılaştırmadan önce trim et: kelimeden sonra boşluk bırakan bir kullanıcı aksi halde 'blue ' gönderir, bu da 'blue''ya eşit değildir.
Girdiyi satır satır okumak
Girdi bitene kadar her satırı işlemek için arayüz üzerinde for await ile dön. Bir program kullanıcının yazdığı bir listeyi (Ctrl+D ile biten) ya da node index.js < numbers.txt ile içine pipe'lanan bir dosyayı böyle okur. Eski kod aynı şeyi event'lerle yapar: her satır için rl.on('line', fn), sonda rl.on('close', fn); döngü bu event çiftinin yukarıdan aşağı yazılmış hâlidir:
Program 3 numbers, total 49 yazdırdı ve döngü girdi bitince kendiliğinden sona erdi, yani close() gerekmiyor. Dördüncü bir girdi satırı, 1, ekle; sonuç 4 numbers, total 50 olur.
Tüm stdin'i tek seferde okumak
Başka bir programdan pipe'lanan girdi için (cat data.txt | node index.js) her şeyi tek çağrıda okumak daha basittir. 0 numaralı file descriptor standart girdidir. Windows'ta kaydedilmiş bir dosyanın satırları \r\n ile bitebilir, bu yüzden girdi oradan gelebiliyorsa /\r?\n/ ile böl:
Program üç ürünü bir sütun hâlinde yazdırdı. readFileSync(0) girdi tamamlanana kadar bloklar; bu, bir pipe okuyan script ve testler için sorun değildir, ama etkileşimli bir araç için yanlıştır, çünkü kullanıcı daha hiçbir soru görmeden her şeyi yazmak zorunda kalır.
Hangisini kullanmalı
Dördü de aynı standart girdiyi okur. Farkları, kodunun metni ne zaman aldığıdır: her seferinde bir cevap, her seferinde bir satır ya da en sonda hepsi birden.
| İhtiyaç | Kullan |
|---|---|
| Sırayla birkaç soru sormak | await rl.question() ile readline/promises |
| 17'den eski Node.js sürümlerini desteklemek | question() callback'i ile readline |
| Her satırı geldikçe işlemek | for await (const line of rl) |
| stdin'den bütün bir pipe'ı ya da dosyayı okumak | fs.readFileSync(0, 'utf8') |
| Program başlamadan bilinen değerler | Bunun yerine process.argv |
Sık yapılan hatalar
rl.close()'u unutmak. Arayüz standart girdiyi açık tutar, bu yüzden program son sorudan sonra hiç kapanmaz. Tüm cevapları aldığında onu kapat.
Cevabı sayı gibi kullanmak. Terminalde yazılan her şey gibi cevap da bir string'dir. '36' + 1 ifadesi '361' olur; önce Number() ile çevir.
Birden fazla soruya birden fazla cevabı pipe'lamak. Girdi klavyeden değil de bir pipe'tan geldiğinde readline hepsini birden okur ve question() sorulmadan önce gelen bir satır kaybolur. Pipe'lanan girdi için for await döngüsünü ya da readFileSync(0) kullan.
output seçeneğini atlamak. output: process.stdout olmadan question() sorusunu hiç yazdırmaz ve kullanıcı boş bir terminale bakar kalır. Satır satır okuyan döngünün buna ihtiyacı yoktur, çünkü bir şey yazdırmaz.
Sıkça Sorulan Sorular
Node.js'te prompt neden tanımlı değil?
prompt() bir diyalog açan tarayıcı fonksiyonudur ve Node.js'te onu açacak bir pencere yok. Node.js'te readline kullan, menüler ve parola alanları için de prompts ya da inquirer gibi bir paket.
Parolayı göstermeden nasıl okurum?
readline basılan her tuşu ekrana yansıtır. prompts ya da @inquirer/password gibi paketler girdiyi gizler; bunu kendin yapmak, terminali process.stdin.setRawMode(true) ile raw moda geçirip her tuşu tek tek işlemek demektir.
readline mı kullanmalıyım, process.argv mi?
Değerler program başlamadan önce biliniyorsa process.argv kullan; böylece program başında kimse olmadan bir script içinde çalışabilir. Ardı ardına soru soran etkileşimli araçlar için readline kullan.