Programlama dünyasında asenkron yani eş zamansız olarak tabir edilen fonksiyonlar, yürütülen diğer fonksiyonlara paralel olarak çalışırlar.
Neden asenkron?
Asenkron işlemler, kod içerisinde çalıştırılan bir fonksiyonun ne kadar zaman alınacağı veya ne zaman tamamlanacağı bilinmediği durumlarda tercih edilirler. Örneğin aşağıdaki işlemlerin ne kadar süreceği bilinemez;
- API’den talepte bulunmak.
- Dosya okuma ve yazma işlemleri.
- Veritabanında işlem yapmak.
- Email göndermek.
Asenkron fonksiyonlar “sen diğer işlemlere devam et, benim işim bittiğinde ben sana haber ederim” yönteminde çalışırlar. Asenkron fonksiyonlar bize haber etmek için callback diye adlandırılan fonksiyonları kullanılırlar.
setTimeout() örneği
Javascript programlamada asenkron işlemlere örnek olabilecek en basit fonksiyon setTimeout()
fonksiyonudur. setTimeout(callback, miliseconds)
fonksiyonu iki parametre alır. Parametrelerden biri işlem bittiğinde çalıştırılacak olan callback fonksiyonu, diğeri ne kadar bekleneceğidir. Belirlenen süre kadar bekledikten sonra, parametre olarak aldığı fonksiyonu çalıştırır.
function notify() {
console.log("Notification!");
}
setTimeout(notify, 3000);
Örnekte, 3 saniye bekledikten sonra callback olarak belirlenen notify()
fonksiyonu çalıştırılır.
Asenkron fonksiyonlar çağrıldığında, hemen ardından çalıştırılan kod asenkron fonksiyonun bitmesini beklemek zorunda değildir.
function notify() {
console.log("Notification!");
}
setTimeout(notify, 3000);
console.log("Merhaba!");
Yukardaki örnekte sırayla;
- Önce setTimeout() süreci başlatılır.
- Konsola “Merhaba!” yazılır.
- 3 saniye dolduktan sonra konsola “Notification!” yazılır.
Callback hell
Callback hell(cehennem) kavramı, callback fonksiyonlar içerisinde tekrar asenkron fonksiyonların ardı ardına çağırılmasıyla oluşan karışık ortama verilen isimdir.
İşlemler dizisi şu şekilde olsun:
- Ayarlar dosyasını oku ve API url bilgisini al.
- API url talebi gönder ve iş listesini al.
- Listedeki iş listesini başka bir API’ye Post olarak gönder
fs.read("settings.json", function(error, result){
http.get(result.toDoUrl, function(toDoResponse){
toDoResponse.todos.forEach(item=> {
http.post(result.customerToDoUrl, item,
function(response){
console.log(response);
})
});
}
})
İşlem adımı ne kadar fazlaysa iç içe geçen işlemler dizisi o kadar uzun olacaktır.
Javascript programlama dilinde callback hell’den kurtulabilmek ya da daha düzenli hale getirebilmek için Promise yöntemi uygulanmaya başlandı. Ancak bu sefer de promise hell oluşmaya başladı.
Bu sorunlardan bizi kurtaran modern javascript kavramı async/await olmuştur.
async/await
Yukarıdaki işlemi async/await ile aşağıdaki şekilde de kullanabiliriz.
const settings = await fs.read("settings.json");
const todoResponse = await http.get(result.toDoUrl);
todoResponse.todos.forEach(item => {
const response = await http.post(result.customerToDoUrl, item);
console.log(response);
})