node:util, Node.js'in yardımcı fonksiyonlar modülüdür. En çok kullanılan iki fonksiyonu util.promisify() ve util.inspect()'tir: promisify, son argümanı (err, deger) biçiminde callback olan eski tarz bir fonksiyonu Promise döndüren bir fonksiyona çevirir; inspect ise herhangi bir değerin hata ayıklama için okunabilir string karşılığını üretir ve console.log'un nesneleri yazdırırken kullandığı mekanizmadır. Modülde bunların yanında callbackify, format, types, deprecate ve isDeepStrictEqual gibi araçlar da bulunur.
Bu yazıda bu fonksiyonların davranışını, sınırlarını ve sık yapılan hataları Node.js v26.13.0 ile çalıştırılmış örneklerle anlatıyoruz. util.styleText, util.parseArgs ve util.parseEnv gibi aynı modüldeki diğer fonksiyonlar serinin başka yazılarında işleniyor; yazının sonunda hangisinin nerede anlatıldığını gösteren bir tablo var. Serinin tamamı için Node.js öğrenme rehberi sayfasına bakabilirsiniz.
util.promisify(): callback API'sini Promise'e çevirmek

util.promisify(original), Node.js'teki yaygın "önce hata" (error-first) callback stilini izleyen bir fonksiyon alır ve aynı işi yapan, Promise döndüren bir sürümünü verir. Callback'e hata gelirse Promise reddedilir, null gelirse ikinci argümanla çözülür. Böylece eski API'leri await ile kullanabilirsiniz. Callback stilinin kendisi için callback fonksiyon yazısına, Promise'in temelleri için Promise yazısına bakın.
import { promisify } from 'node:util';
import { stat } from 'node:fs';
const statAsync = promisify(stat);
const bilgi = await statAsync(import.meta.filename);
console.log('dosya mı:', bilgi.isFile());
try {
await statAsync('olmayan-dosya.txt');
} catch (err) {
console.log(err.code, err.syscall);
}
// çıktı: dosya mı: true
// çıktı: ENOENT statÇekirdek modüllerin çoğu için bunu yapmanıza gerek yoktur: node:fs/promises gibi Promise tabanlı sürümler zaten mevcuttur; üç API biçiminin farkı fs.promises, callback ve sync yazısında anlatılıyor. promisify asıl değerini, yalnızca callback sunan eski kütüphanelerde ve kendi yazdığınız callback tabanlı fonksiyonlarda gösterir:
import { promisify } from 'node:util';
function eskiApi(sayi, callback) {
setTimeout(() => {
if (sayi < 0) return callback(new RangeError('negatif olamaz'));
callback(null, sayi * 2);
}, 5);
}
const yeniApi = promisify(eskiApi);
console.log(await yeniApi(21));
await yeniApi(-1).catch((e) => console.log(e.name, e.message));
class Sayac {
constructor() { this.deger = 42; }
oku(cb) { cb(null, this.deger); }
}
const s = new Sayac();
const okuBagli = promisify(s.oku).bind(s);
console.log(await okuBagli());
try {
await promisify(s.oku)();
} catch (e) {
console.log(e.constructor.name, e.message);
}
// çıktı: 42
// çıktı: RangeError negatif olamaz
// çıktı: 42
// çıktı: TypeError Cannot read properties of undefined (reading 'deger')Örneğin ikinci yarısı belgelerdeki uyarıyı gösteriyor: this kullanan sınıf metotlarını doğrudan promisify ederseniz, dönen fonksiyon çağrıldığında this kaybolur. Çözüm, sonucu bind(nesne) ile bağlamak ya da .call(nesne) ile çağırmaktır. Belgeler iki kuralı daha belirtir: promisify() her durumda callback'in son argüman olduğunu varsayar ve original bir fonksiyon değilse hata fırlatır.
util.promisify.custom: kendi Promise sürümünüzü tanımlamak
Bazı fonksiyonlar standart (err, deger) stiline uymaz; örneğin başarı ve hata için iki ayrı callback alırlar. Böyle bir fonksiyonun util.promisify.custom sembolüyle bir özelliği varsa promisify() sarmalama yapmaz, doğrudan o özelliğin değerini döndürür. Belgelere göre bu sembol global sembol kayıt defterine de kayıtlıdır ve her ortamda Symbol.for('nodejs.util.promisify.custom') olarak erişilebilir; böylece kütüphaneniz node:util'i içe aktarmadan da destek sunabilir. Sembollerin genel davranışı için Symbol yazısına bakın.
import { promisify } from 'node:util';
function indir(url, basarili, hatali) {
setTimeout(() => (url ? basarili(`içerik: ${url}`) : hatali(new Error('url yok'))), 5);
}
indir[promisify.custom] = (url) => new Promise((resolve, reject) => indir(url, resolve, reject));
const indirAsync = promisify(indir);
console.log(indirAsync === indir[promisify.custom]);
console.log(await indirAsync('/rapor.pdf'));
console.log(promisify.custom === Symbol.for('nodejs.util.promisify.custom'));
// çıktı: true
// çıktı: içerik: /rapor.pdf
// çıktı: truepromisify.custom tanımlı ama fonksiyon değilse belgelere göre promisify() hata fırlatır.
Zaten Promise döndüren fonksiyonu promisify etmek: DEP0174
Async bir fonksiyonu promisify etmek yaygın bir hatadır. Async fonksiyon callback'i hiç çağırmaz, döndürdüğü Promise'in sonucu da yok sayılır; bu yüzden dönen Promise hiç sonuçlanmaz. Kullanımdan kaldırma belgesi bunun işlenmemiş Promise retlerine de yol açabileceğini belirtir. YAML kaydına göre bu kullanım v20.8.0'da belge düzeyinde, v21.0.0'da çalışma zamanı düzeyinde (Runtime) DEP0174 koduyla kullanımdan kaldırıldı ve Node.js bir uyarı yazar:
import { promisify } from 'node:util';
async function zatenAsync(cb) {
return 'sonuç';
}
const yanlis = promisify(zatenAsync);
yanlis().then((v) => console.log('çözüldü:', v));
setTimeout(() => console.log('100 ms geçti, söz hâlâ bekliyor'), 100);
// çıktı: 100 ms geçti, söz hâlâ bekliyor
// stderr: (node:56576) [DEP0174] DeprecationWarning: Calling promisify on a function that returns a Promise is likely a mistake.
// stderr: (Use `node --trace-deprecation ...` to show where the warning was created)çözüldü satırı hiç yazılmadı. Fonksiyon zaten Promise döndürüyorsa doğrudan await edin; promisify'a gerek yoktur. Kullanımdan kaldırma kodlarının nasıl okunacağı için DEP kodları yazısına bakın.
util.callbackify(): ters yönde dönüşüm
util.callbackify(original), async bir fonksiyonu (ya da Promise döndüren bir fonksiyonu) alır ve son argüman olarak (err, deger) callback'i bekleyen bir fonksiyona çevirir. Callback'in ilk argümanı ret sebebidir (Promise çözüldüyse null), ikincisi çözülen değerdir. Callback bekleyen eski bir arayüze yeni async kod bağlarken işe yarar.
import { callbackify } from 'node:util';
async function fiyatGetir(kod) {
if (!kod) throw new Error('kod gerekli');
return { kod, fiyat: 99.9 };
}
const fiyatCb = callbackify(fiyatGetir);
fiyatCb('A1', (err, sonuc) => console.log(err, sonuc));
fiyatCb('', (err) => console.log('hata:', err.message));
const nullRed = callbackify(() => Promise.reject(null));
nullRed((err) => console.log(err instanceof Error, err.message, err.reason));
// çıktı: null { kod: 'A1', fiyat: 99.9 }
// çıktı: hata: kod gerekli
// çıktı: true Promise was rejected with falsy value nullSon satır belgelerdeki özel durumu gösteriyor: callback'te ilk argümanın null olması "hata yok" anlamına geldiği için, Promise null gibi falsy bir değerle reddedilirse bu değer bir Error içine sarılır ve asıl değer reason alanında saklanır. Belgeler ayrıca callback'in asenkron çalıştığını ve callback içinde hata fırlatılırsa sürecin 'uncaughtException' yayacağını, işlenmezse kapanacağını belirtir; bu olay için uncaughtException yazısına bakın.
util.inspect(): değerleri okunabilir string'e çevirmek

util.inspect(nesne[, secenekler]), hata ayıklama amacıyla bir değerin string gösterimini döndürür. console.log() bir nesneyi yazdırırken aynı mekanizmayı kullanır. Belgeler önemli bir uyarı yapar: inspect çıktısı her an değişebilir ve programatik olarak ona güvenilmemelidir; yani bu çıktıyı ayrıştırmak ya da bir API yanıtı olarak kullanmak doğru değildir. Veri aktarmak için JSON.stringify kullanın.
import { inspect } from 'node:util';
const veri = { kullanici: { profil: { adres: { il: 'İzmir' } } }, roller: ['admin'] };
console.log(veri);
console.log(inspect(veri, { depth: null }));
console.log(inspect(veri, { depth: 0 }));
console.log(inspect({ b: 2, a: 1, c: [3, 1, 2] }, { sorted: true, compact: true }));
console.log(inspect(1234567.891, { numericSeparator: true }));
const dongu = { ad: 'kök' };
dongu.kendisi = dongu;
console.log(inspect(dongu));
// çıktı: { kullanici: { profil: { adres: [Object] } }, roller: [ 'admin' ] }
// çıktı: {
// çıktı: kullanici: { profil: { adres: { il: 'İzmir' } } },
// çıktı: roller: [ 'admin' ]
// çıktı: }
// çıktı: { kullanici: [Object], roller: [Array] }
// çıktı: { a: 1, b: 2, c: [ 3, 1, 2 ] }
// çıktı: 1_234_567.891
// çıktı: <ref *1> { ad: 'kök', kendisi: [Circular *1] }İlk satır, console.log'un varsayılan derinliğinin 2 olduğunu gösteriyor: üçüncü seviyeden sonrası [Object] olarak kısaltılıyor. Bu, iç içe yapılandırma nesnelerini loglarken en sık karşılaşılan şaşkınlıktır. depth: null (ya da Infinity) tüm seviyeleri açar. sorted, nesne anahtarlarını ve Map/Set girdilerini sıralar; dizinin elemanlarına dokunmaz. Döngüsel referanslar <ref *1> ve [Circular *1] işaretleriyle gösterilir.
| Seçenek | Varsayılan | Ne yapar |
|---|---|---|
| depth | 2 | Kaç seviye iç içe yapı açılacağı; null veya Infinity hepsini açar |
| colors | false | ANSI renk kodlarıyla çıktı |
| showHidden | false | Numaralandırılamayan özellikler ve semboller de gösterilir |
| maxArrayLength | 100 | Gösterilecek en fazla dizi, Map, Set elemanı |
| maxStringLength | 10000 | Gösterilecek en fazla karakter |
| breakLength | 80 | Çıktının satırlara bölüneceği uzunluk |
| compact | 3 | Kaç iç elemanın tek satırda birleştirileceği; false her anahtarı yeni satıra koyar |
| sorted | yok | true veya karşılaştırma fonksiyonu ile anahtarları sıralar |
| customInspect | true | false ise util.inspect.custom fonksiyonları çağrılmaz |
| numericSeparator | false | Sayılarda üç basamakta bir alt çizgi koyar |
Varsayılanları süreç genelinde değiştirmek için util.inspect.defaultOptions nesnesine değer atayabilirsiniz; belgelere göre bu, inspect'i dolaylı olarak kullanan console.log ve util.format gibi fonksiyonları da etkiler. Örneğin inspect.defaultOptions.depth = null tüm loglarda nesneleri sonuna kadar açar. Konsol çıktısının diğer yönleri için console ve util.styleText yazısına bakın.
util.inspect.custom: nesnenin nasıl görüneceğini belirlemek
Bir sınıfa [util.inspect.custom] metodu eklerseniz inspect ve dolayısıyla console.log, nesneyi bu metodun döndürdüğü değerle gösterir. Belgelere göre sembol Symbol.for('nodejs.util.inspect.custom') olarak global kayıt defterindedir; bu sayede kod tarayıcıda da çalışır, orada metot sadece yok sayılır. Bu özellik, parola veya token gibi hassas alanların loglara sızmasını önlemek için kullanışlıdır:
import { inspect } from 'node:util';
class Parola {
#deger;
constructor(deger) { this.#deger = deger; }
[inspect.custom]() {
return 'Parola <gizli>';
}
}
const p = new Parola('s3cr3t');
console.log(p);
console.log({ kullanici: 'ali', parola: p });
console.log(inspect(p, { customInspect: false }));
// çıktı: Parola <gizli>
// çıktı: { kullanici: 'ali', parola: Parola <gizli> }
// çıktı: Parola {}util.format(): printf benzeri biçimlendirme
util.format(bicim, ...argumanlar), ilk argümandaki biçim belirteçlerini sırayla diğer argümanlarla doldurur. console.log'a birden fazla argüman verdiğinizde aynı kurallar uygulanır. Desteklenen başlıca belirteçler: %s (string), %d (Number), %i (parseInt), %f (parseFloat), %j (JSON), %o ve %O (nesne gösterimi), %% (tek yüzde işareti). %c CSS içindir ve Node.js'te yok sayılır.
import { format } from 'node:util';
console.log(format('%s adlı kullanıcı %d kez giriş yaptı', 'Zeynep', 3));
console.log(format('%i | %f | %j', '42.9px', '3.14abc', { a: 1 }));
console.log(format('%o', [1]));
console.log(format('%s:%s', 'eksik'));
console.log(format('fazla', 'argüman', 7, { x: 1 }));
console.log(format('yüzde: %%d %d', 5));
// çıktı: Zeynep adlı kullanıcı 3 kez giriş yaptı
// çıktı: 42 | 3.14 | {"a":1}
// çıktı: [ 1, [length]: 1 ]
// çıktı: eksik:%s
// çıktı: fazla argüman 7 { x: 1 }
// çıktı: yüzde: %d 5Belgelerdeki kurallar çıktıda görülüyor: karşılığı olmayan belirteç olduğu gibi kalır (eksik:%s), fazla argümanlar boşlukla eklenir ve string olmayanlar inspect ile biçimlendirilir. %o, showHidden: true benzeri davrandığı için dizinin gizli length özelliğini de gösteriyor. Belgeler util.format()'ın senkron bir hata ayıklama aracı olduğunu, bazı girdilerde event loop'u bloklayacak kadar maliyetli olabileceğini ve sık çalışan kod yollarında kullanılmaması gerektiğini vurgular.
util.types ve Error.isError(): tip kontrolleri
util.types, yerleşik nesne türleri için tip kontrolleri sunar: isPromise, isDate, isRegExp, isMap, isAsyncFunction, isGeneratorFunction, isTypedArray ve daha fazlası. Belgelere göre bu kontroller instanceof veya Object.prototype.toString.call()'dan farklı olarak JavaScript'ten erişilebilen özelliklere (ör. prototipe) bakmaz ve genellikle C++ tarafına çağrı maliyeti taşır. Belgeler bunları özellikle eklenti (addon) geliştiricileri için yararlı bulur.
import { types } from 'node:util';
console.log(types.isPromise(Promise.resolve()), types.isPromise({ then() {} }));
console.log(types.isDate(new Date()), types.isRegExp(/a/), types.isMap(new Map()));
console.log(types.isAsyncFunction(async () => {}), types.isGeneratorFunction(function* () {}));
console.log(Error.isError(new TypeError('x')), Error.isError({ message: 'sahte' }));
// çıktı: true false
// çıktı: true true true
// çıktı: true true
// çıktı: true falsetypes.isPromise, yalnızca then metodu olan bir nesneyi (thenable) Promise saymaz. Hata nesnesi kontrolü için util.types.isNativeError() v24.2.0'da kullanımdan kaldırıldı (DEP0197); belgeler yerine Error.isError() önerir, ancak Node.js 24 itibarıyla Error.isError()'un daha yavaş olduğunu, performans kritikse ikisini kendi ortamınızda ölçmenizi de not eder. Eski util.isArray(), util.isError() gibi tip fonksiyonları da kullanımdan kaldırıldı: util.isArray() çalışma zamanı uyarısı veriyor (DEP0044, Runtime), util.isError() ise v23.0.0'da End-of-Life olarak tamamen kaldırıldı (DEP0048). Hata yönetimi için try/catch yazısına bakın.
util.deprecate(): kendi API'nizi kullanımdan kaldırmak
Bir kütüphane geliştiriyorsanız, eski bir fonksiyonu kaldırmadan önce kullanıcıları uyarmak için util.deprecate(fn, mesaj[, kod]) kullanabilirsiniz. Dönen sarmalayıcı, ilk çağrıldığında 'warning' olayı üzerinden bir DeprecationWarning yayar ve stderr'e yazar; sonraki çağrılar uyarısız çalışır. Aynı kod birden çok deprecate() çağrısında kullanılırsa uyarı o kod için yalnızca bir kez verilir.
import { deprecate } from 'node:util';
const eskiTopla = deprecate((a, b) => a + b,
'eskiTopla() kullanımdan kalkıyor, topla() kullanın.', 'UYG001');
console.log(eskiTopla(1, 2));
console.log(eskiTopla(3, 4));
// çıktı: 3
// çıktı: 7
// stderr: (node:41752) [UYG001] DeprecationWarning: eskiTopla() kullanımdan kalkıyor, topla() kullanın.
// stderr: (Use `node --trace-deprecation ...` to show where the warning was created)Davranış komut satırı bayraklarıyla değiştirilebilir: --no-deprecation veya --no-warnings uyarıyı kapatır, --trace-deprecation yığın izini de yazar, --throw-deprecation ise uyarı yerine hata fırlatır ve diğerlerinden önceliklidir. Aynı ayarlar process.noDeprecation, process.traceDeprecation ve process.throwDeprecation özellikleriyle de yapılabilir.
util.isDeepStrictEqual(): derin eşitlik
İki nesnenin içerik olarak aynı olup olmadığını === ile anlayamazsınız; o yalnızca aynı referans olup olmadıklarına bakar. util.isDeepStrictEqual(a, b) derin ve katı (strict) eşitliği kontrol eder: türler de eşleşmelidir ve varsayılan olarak prototip ile constructor da karşılaştırılır. v24.9.0 ile gelen skipPrototype seçeneği prototip karşılaştırmasını atlar. JavaScript'teki eşitlik operatörleri hakkında daha fazlası için eşitlik operatörleri yazısına bakın.
import { isDeepStrictEqual } from 'node:util';
const a = { id: 1, etiketler: ['x', 'y'] };
const b = { id: 1, etiketler: ['x', 'y'] };
console.log(a === b, isDeepStrictEqual(a, b));
console.log(isDeepStrictEqual({ n: 1 }, { n: '1' }));
console.log(isDeepStrictEqual([NaN], [NaN]));
class Nokta { constructor(x) { this.x = x; } }
console.log(isDeepStrictEqual(new Nokta(1), { x: 1 }));
console.log(isDeepStrictEqual(new Nokta(1), { x: 1 }, { skipPrototype: true }));
// çıktı: false true
// çıktı: false
// çıktı: true
// çıktı: false
// çıktı: trueTestlerde aynı karşılaştırmayı assert.deepStrictEqual() yapar; fark, isDeepStrictEqual'ın hata fırlatmak yerine boolean döndürmesidir. Test yazımı için node:test yazısına bakabilirsiniz.
util modülündeki diğer fonksiyonlar nerede?

node:util oldukça geniş bir modüldür. Aşağıdaki fonksiyonlar bu seride kendi bağlamlarında anlatılıyor; util.debuglog(bolum) ise NODE_DEBUG ortam değişkeninde bölüm adı geçtiğinde stderr'e yazan, geçmediğinde hiçbir şey yapmayan bir log fonksiyonu üretir.
| Fonksiyon | Ne yapar | Anlatıldığı yer |
|---|---|---|
| util.styleText | Terminal çıktısını renklendirir | console ve util.styleText yazısı |
| util.parseArgs | Komut satırı argümanlarını ayrıştırır | process.argv ve çıkış kodları yazısı |
| util.parseEnv | .env biçimindeki metni ayrıştırır | --env-file ve process.env yazısı |
| util.aborted, util.transferableAbortSignal | AbortSignal yardımcıları | AbortController yazısı |
| util.getSystemErrorName | Sayısal sistem hata kodunu ada çevirir | Sistem hataları yazısı |
| util.debuglog | NODE_DEBUG ile koşullu log | Bu yazı |
İlgili yazılar: util.styleText, util.parseArgs, util.parseEnv, util.aborted, sistem hata kodları.
Sık yapılan hatalar
- Sınıf metodunu bağlamadan promisify etmek:
thiskaybolur veTypeErroralırsınız.promisify(nesne.metot).bind(nesne)yazın. - Async fonksiyonu promisify etmek: Dönen Promise hiç sonuçlanmaz ve DEP0174 uyarısı çıkar. Async fonksiyonu doğrudan
awaitedin. - console.log çıktısında [Object] görünce verinin eksik olduğunu sanmak: Varsayılan derinlik 2'dir.
inspect(x, { depth: null })veyaconsole.dir(x, { depth: null })kullanın. - inspect çıktısını ayrıştırmak: Belgelere göre biçim her an değişebilir. Makine tarafından okunacak veri için JSON kullanın.
- Sık çalışan kodda util.format kullanmak: Belgeler bunun event loop'u bloklayabileceği konusunda uyarır; sıcak kod yollarında kaçının.
- util.isArray, util.isError gibi eski fonksiyonları aramak: Bunlar kullanımdan kaldırıldı,
util.isError()gibi bazıları artık hiç yok;Array.isArray()veError.isError()kullanın.
Sık Sorulan Sorular
util.promisify ile fs.promises arasındaki fark nedir?
fs.promises (node:fs/promises), Node.js'in hazır sunduğu Promise tabanlı dosya sistemi API'sidir. promisify ise herhangi bir callback tabanlı fonksiyonu sizin dönüştürmenizi sağlar. Hazır Promise sürümü varsa onu kullanın; promisify'ı yalnızca callback sunan kodlar için saklayın.
console.log neden iç içe nesneleri [Object] olarak gösteriyor?
console.log nesneleri util.inspect ile biçimlendirir ve varsayılan depth değeri 2'dir. Daha derin seviyeler kısaltılır. util.inspect(nesne, { depth: null }) ile tamamını görebilir ya da util.inspect.defaultOptions.depth değerini değiştirebilirsiniz.
util.inspect.custom ile toJSON aynı şey mi?
Hayır. inspect.custom yalnızca util.inspect ve console.log gibi inspect tabanlı çıktıyı etkiler; toJSON ise JSON.stringify()'ın kullandığı metottur. Hassas veriyi her iki çıktıda da gizlemek istiyorsanız ikisini de tanımlamanız gerekir.
util.types.isNativeError yerine ne kullanmalıyım?
Node.js belgeleri Error.isError() kullanmanızı önerir; isNativeError v24.2.0'dan beri kullanımdan kaldırılmış durumdadır (DEP0197). Belgeler Node.js 24 itibarıyla Error.isError()'un daha yavaş olduğunu not eder; performans kritik bir yoldaysanız kendi ortamınızda ölçün.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Node.js öğrenme rehberi · console ve util.styleText · fs.promises, callback ve sync · Deprecation uyarıları · JavaScript callback fonksiyon