Back to Top

Category Archives: Kategorisiz

Bu iyi – async await Promise

JavaScript Promise kullanımı – Promise Sözdizimi

JavaScript Promise kullanımı;

Promise Sözdizimi

  • Promise’leri new öneki ile tanımlıyoruz.
  • Başarılı (resolve) ve başarısız (reject) durumlarda çağıralacak iki fonksiyon ile birlikte oluşturuyoruz. (Sıralamayı değiştirmemek kaydıyla bu iki fonksiyona farklı isimler de verebilirsiniz ancak genelde bu isimler tercih edilmektedir.)
  • Promise’leri bir değişkene atayabiliriz. (Örnekteki sozVerdik değişkeni gibi.)
  • Promise beklenilen işlemi gerçekleştirdikten sonra yapılacak adımlar için .then() fonksiyonu çağırılır. İçerisindeki fonksiyonun parametresi resolve() ile gönderilen parametredir.
  • Eğer istek dahilinde reject() çağırıldığında veya öngörülemeyen bir hata sonucu promise başarısız olduğunda .then() fonksiyonu es geçilerek, .catch() içerisindeki fonksiyon çağırılır ve hatalı durumda yapılacak adımlar izlenir.

Promise Zincirleri

Zincir diyerek kastettiğim şu: biri diğerini bekleyen asenkron işlemlerin arka arkaya çalıştırılması.

Promise yapısı gereği asenkrondur ve uygulamadaki bekleyen diğer kodların çalışmasını bekletmez. Bu yüzden sıralı asenkron işlemlerin birbirini beklemesi için promise zinciri diyebileceğimiz yapılar oluşturmamız gerekir.

Yukarıdaki kod parçacığı üzerinden promise zincilerine bir bakalım:

Birden fazla .then() arka arkaya eklenerek oluşturulur.
Zinciri başlatan bir promise olduğu gibi .then() içindeki fonksiyonların dönüş değeri de promise olur. return değeri promise’leştirilerek zincirin diğer halkasına aktarılır. Bu yüzden zincirin her bir halkasını promise okuyan ve promise çıktısı oluşturan bir yapı olarak düşünebiliriz.
Hataların yakalanması için tek bir .catch() yeterlidir. Zincir içerisinde ne zaman başarısız (rejected) bir promise veya beklenmedik bir hata oluşursa, sonrasındaki .then() halkaları atlanılarak .catch() içerisindeki fonksiyon çalışır. asenkronIslem, baskaAsenkronIslem, birinci veya ikinci .then()’in hatalı sonuçlanması konsola hata mesajının basılması ile sonuçlanır.

Kuran Okuma ve Sayfa İlerleme Kodları

Kuran Okuma ve Sayfa İlerleme Kodları

Node Js ile json dosyasından okuyarak mysql dosyasına toplu kayıt işlemleri.

Synchronous Programlama Nedir?

Synchronous programlamada işlemler sırayla gerçekleşir. Başka bir deyişle bir işlem bitmeden diğerine geçiş yapılmaz. Aktif olan devam ederken sıradaki işlem bloklanır.

Bildiğiniz gibi Javascript bir single-threaded programlama dilidir. Yani kodu satır satır okur ve sırayla işleme sokar. Bu nedenle yukarıda verilen örneğin outputu şu şekildedir.

Asynchronous Programlama Nedir?

Callbacks, Promise ve Async-Await

Bir örnek üzerinden bu yöntemleri, aralarındaki farkları ve kullanım kolaylıklarını inceleyelim.

Diyelimki random zamana bağlı olarak string yazdıran bir fonksiyonumuz var.
Bu fonksiyonu kullanarak A, B, C harflerini sırayla yazdıralım.

Her ne kadar sırayla çağırılmış olsalar da printAll fonksiyonu her çağırıldığında A, B, C harfeleri farklı sırayla loglanır. Daha önceden de açıkladığım gibi printString fonksiyonu asynchronous çalışır. A, B, C için her fonksiyon sırayla çalıştırılır ancak setTimeOut fonksiyonundan dolayı farklı zamanlarda gercekleşirler. Bu da A, B, C harflerinin farklı sırayla loglanmasına sebep olur.

Peki bir fonsiyonu art arda kullanmak istiyorsak ve sırayla gercekleşmesini bekliyorsak ne yapmalıyız? Bu sorunun cevabına geçmeden önce de buna neden ihtiyaç duyduğumuzu da belirtmek istiyorum.

Bu tarz işlemlere bir yere istek atarken ve o istekten dönen cevaplara göre kodun devamını getiriyorsak ihtiyaç duyabiliriz. Çünkü kodu sırayla yazsak bile istek atan fonksiyon satırı okunup isteğin cevabına göre işlemi gerçekleştirecek olan fonksiyon satırına geçildiğinde eğer istek bir cevap dönmediyse undefined hatası ile karşılaşırız. Bu hata ile karşılaşmak istemiyorsak da Promise in resolve olduğu yere istekten gelen cevap ile işlem yapan fonksiyonu çağırabiliriz. Aynı zamanda bu isteğin dönmesini beklerken çalışan kodun bulunduğu satırdan sonrası için çalışmayı durdurur. Bu tarz hataların önüne geçebilmek için de calbackler,promiseler ve async-await kullanılır.

Callbacks

Callback fonksiyonları bağımsız bir değişken olarak başka bir fonksiyona geçirilen ve ilk fonksiyonun işlemi tamamlandıktan sonra diger fonksiyonun işlevini başlatan fonksiyonlardır. Callbackler genellikle asynchronous işlemler tamamlandıktan sonra kod yürütülmesine devam etmek için kullanılır.

Gelin bir örnekle duruma göz atalım.

Şimdi de addAll fonksiyonunu kullanarak A,B, C harflerini yazdıralım.

Gördüğünüz gibi bu sefer A,B, C harflerini sırayla yazdırmayı başardık lakin kodumuz oldukça karışık gözüküyor. Zaten callbakleri nerede ve ne zaman kullanacağımıza bu nedenle özen göstermeliyiz. Çünkü fonksiyon içinde fonksiyonları kullanmaya başladıkça kodu okumak gittikçe zorlaşacak ve zamanla “Callback Hell” adı verilen problem ortaya çıkacak. Ayrıca Callbacklerin sebep olduğu bazı hatalar da vardır. Bu hatalardan bazıları şunlardır;

  • Callback’in beklenenden erken çağrılması,
  • Callback’in hiç çağrılmaması,
  • Callback’in beklenilenden az veya çok çağrılması,
  • Gerekli parametreleri doğru bir şekilde alamaması,
  • Hataların kontrolünde zayıflık

Peki bu hataları yaşamamak için ve işlevlerimi yerine getirmek için hangi yolu izlemeliyiz? Bu sorunun cevabı için gelin beraber bir de promiselere göz atalım.

Promise

Promiseler benim gibi Javascript’e yeni başlayan yazılımcılar için büyük ihtimalle en çekimser yaklaşılan konulardan biridir. Peki nedir bu promiseler?
Promiseler, ‘Callback Hell’ durumundan kaçınmak için ve beklenmeyen durumla karşılaşıldığında hata kontrolünün daha rahat yapılabilmesi için geliştirilmiş ES6 olarak bilinen ECMAScript 2015 ile bize sunulan asynchronous bir yapıdır.

Bir promise 3 durumdan oluşur;

  • Pending: Bu başlangıç aşamasıdır. Bu aşamada bir şey gerçekleşmez. Bu aşama için şöyle düşünebiliriz, müşteri sana bir sipariş verecektir. Ama henüz bir şey sipariş etmemiştir.
  • Resolved: Bu aşama ise işlemin sonuçlandığı ve başarılı olduğu aşamadır. Yani müşteri siparişini almış ve memnun kalmıştır.
  • Rejected: Bu aşama ise hata ile sonuçlanan aşamadır. İstenen sipariş gelmemiş ve müşteri restoranı terk etmiştir.

Şimdi gelin beraber addString fonksiyonumuzu promise kullanarak yazalım.

Gördüğünüz gibi callback kullanmak yerine tüm fonksiyonu bir promise içerisine koyduk. Bu promise sonucunda fonksiyonumuz ya resolve olacak ya da reject. Ayrıca promiselerde eğer işlem başarılı olursa then( ), başarısız olursa ve hata durumu olursa catch( ) fonksiyonlarının içine girer. Bu yapıya ise “Promise Chain” denir.

Gördüğünüz gibi A,B, C harflerini sırayla yazdırmayı başardık. Kod yapısına baktığımızda ise ilk fonksiyonun diğer fonksiyonun sonucunu return ettiğini ve sonucun bir sonraki fonsiyona gönderildiğini görürüz.

Diğer kısma geçmeden önce promise yapısı ile ilgili promise.all( ) ve promise.race( ), promise.allSettled( ) ve promise.any( ) özelliklerinden de bahsetmek istiyorum.

  • Promise.all( ), birden fazla promise tek bir then( ) ve catch( ) ile yazılabiliyor. Promise’lerden biri reject( ) olursa direk catch( )’e girer. Tüm Promise başarıyla tamamlanmasını bekler.
  • Promise.race( ), ise promiselerden en önce hangi promise tamamlanırsa onun sonucunu alır.
  • Promise.allSettled( ), tüm Promise başarılı, başarısız işletimleri bitince sonuçlarını status leri ile birlikte geriye döner.
  • Promise.any( ), bu yöntem, yerine getiren ilk promisi döndürmek için kullanışlıdır. Bir promise yerine getirildikten sonra kısa devre yapar, bu nedenle bir resolve olmuş bir promise bulduktan sonra diğer promiselerin tamamlanmasını beklemez.

Async / Await

Async/Await yapısı asynchronous işlemleri daha anlaşılması kolay bir hale getiren ECMAScript 2017 ile kullanıma sunulan promise tabanlı bir Javascript özelliğidir.
Anlaşılması kolay derken neyden bahsettiğimi açıklayayım. Şöyle ki biz geliştiriciler olarak, çoğunlukla synchrounous kod yazmaya alışkınız, yani birbiri ardına komut dizileri yazarız. Çünkü bu tarz yazım şeklinin okunması ve anlaşılması çok daha kolaydır. Callbackler ve promiseler döngüsellikleri nedeniyle bizi bu açıdan biraz yorar. Async-await tam olarak o anda yardımımıza koşar.

Şimdi yeniden addString ve addAll() fonksiyonumuza bakalım.

Gördüğünüz gibi A,B ve C harflerini sırayla yazdırmayı başardık.
Ayrıca addAll() fonksiyonu içinde geçen ’’async” sözcüğü JavaScript’in async / await sözdizimini kullandığımızı bilmesini sağlar ve Await kullanmak istiyorsanız bu sözcüğü kullanmanız şarttır. Aksi taktirde hata alırsınız.

Async-Await özelliği istek atarken ve o istekten dönen cevaplara göre işlem yapıyorsak sık kullanılan bir yapıdır. Bu nedenle konuyu da daha iyi anlamamız için son bir örnek daha vermek istiyorum.

Javascript ile json dosyasına kaydetme ve okuma

Client için kodlar.

Node Js server bölümünde de dosya kayıt ediliyor.

Javascript callback fonksiyonu

Javascript’in Asenkron özelliğinin önüne geçmek için callback fonksiyonu kullanılır.

Öncelikle hatırlayalım callback neydi diye. Callback, en basit haliyle herhangi bir fonksiyona parametre olarak verdiğimiz ve sonra geri çağıracağımız fonksiyonlara denir. İstenilen değere ulaştığında veya işlem sonlandığında görevini yerine getirir.

Express.js – Middleware(Ara Katman) Nedir? Nasıl Kullanılır?

Merhaba,

Yazılım dendimi akıllara kompleks ve anlamsız işlemlerden anlamlı sonuçlar üreten bir olgu gelmektedir. Bu kompleks süreçler, son kullanıcılara mümkün mertebe yansıtılmadan programın hizmet edeceği iş ne ise o alana dönük olabildiğince tüm işlemler arayüz odaklı halledilebilir hale getirilmektedir. Tabi süreci sadece son kullanıcı odaklı düşünürsek ilgili yazılımda nihai erişimi arayüzsel seviyede yönetilebilir hale getirmek yeterli olacaktır. Lakin bu işin bir de yazılım geliştiricileri boyutu mevcuttur. Yani kompleks sürecin tam merkezinde yani işin kod ve veri kısmında bulunan yazılım ekibi bu süreci kendi lehlerinde anlamlandırabilirlerse, hem geliştiriciler için hem de yazılımın geleceğe dair gelişimindeki eğilimi için oldukça faydalı katkıda bulunulmuş olacaktır.

Aslında bu anlamlandırma uğraşısı, yazılımın sağlam temellerde inşa edilmesini sağlayacağından dolayı doğru, prensipli ve anlaşılabilir kod inşaasını gerektirecek ve bir yandan da yazılımcılar için projeye hiyerarşik boyut kazandıracak neyin, nerede ve ne amaçla olduğuna dair daha geniş perspektifle ilgili projeye bakış açılarını genişletecek ve verimi arttıracaktır. Yani yazılım geliştiriciler ustaysa eğer inşaatta çekicin çivinin nerede nasıl tutulduğunu bilmeleri işlerinde hızlanmalarını sağlayacaktır.

Teknik boyutta bir projeyi daha anlamlı hale getirmek için öncelikle doğru yaklaşımlarla ilgili proje tasarlanmalıdır. Buda doğru ve detaylı plan gerektirmektedir. Tasarıya dönük olması gerektiği yerlerde ise bir Çinli ile bir başka Aborjin yazılım geliştiricinin birbirlerinin beşeri dillerini bilmeden, birinin yaptığı işi bir diğerinin tek bakışta ve tek seferde anlayabilmesini sağlayacak olan design pattern(tasarım desenleri) yapıları uygulanmalıdır. Tüm bunların yanında proje mümkün mertebe katmansal hale getirilmeli ve tekrardan dünya standartlarında bir katmanlı mimarinin eşliğinde proje temellendirilip ihtiyaca dönük özel katmanlarla genişletilmelidir.

Bu içeriğimizde bizler bir projenin katmansal hale getirilmesini Node.js’in Express.js modülünde küçük bir noktada değerlendirecek ve gelen requestlere karşılık response gönderilmeden araya Middleware şeklinde isimlendirilen ara katman sokacağız. Şimdi gelin Middleware’in ne işe yaradığını ve nasıl kullanıldığını inceleyelim.

Middleware(Ara Katman) Nedir?

Express.js - Middleware(Ara Katman) Nedir? Nasıl Kullanılır?

Klasik web uygulamalarında, kullanıcıdan gelen taleplere(request) karşılık cevaplar(response) gönderilmektedir.

Gelişmiş yapılanmada ise, request – response işlevsel ilişkisinin arasına Middleware girebilmekte ve tek elden ek işlemler icra edilebilmektedir.

Express.js - Middleware(Ara Katman) Nedir? Nasıl Kullanılır?


Middleware katmanı, genellikle tüm route rotalarında yapılacak işlemleri tek elden yönetmek için kullanılmaktadır. Genellikle bu işlemlerden biri kullanıcı oturum kontrolüdür. Her bir route üzerinde bu kontrolü yapmanın ne kadar maliyetli ve lüzumsuz kod israfına yol açacağını siz düşünün…

Şimdi Middleware ile ilgili teknik boyutta değerlendirmelere başlayalım.

01020304050607080910const express = require("express");const app = express(); app.use((request, response, next) => {response.send("Middleware çalıştı.");}); app.get("/", (request, response) => {response.send("Route çalıştı...");}).listen(5000);
Express.js - Middleware(Ara Katman) Nedir? Nasıl Kullanılır?

Yukarıdaki kod bloğunu incelerseniz eğer “app.use” fonksiyonu içerisine tanımlanan callback fonksiyonu ile Middleware’i oluşturmuş oluyoruz. Bu işlemden sonra “app” üzerinden oluşturulan tüm route yapıları için herhangi bir istek söz konusu olursa bu istek karşılığında cevap verilmeden önce ilgili middleware devreye girecektir.

Tamam, istek neticesinde ilgili middleware devreye girdi girmesine ama sanki tetiklenen route çalıştırılmadı la hoca!” diye söyleniyor olabilirsiniz… Evet, haklısınız. Ama bu sorunuzun cevabına gelmeden önce middleware fonksiyonumuzdaki parametrelerden en sonuncusu olan “next” fonksiyonunu inceleyelim.

“next” parametresi yukarıda bahsettiğim gibi bir fonksiyondur. Bu fonksiyon çağrıldığı zaman ilgili middleware’de ki çalışmaların onaylandığı bir başka deyişle doğrulandığı söz konusu olacaktır ve middleware tetiklenmeden önce hangi route’a istek gönderildiyse o route bu doğrulama neticesinde çalıştırılacaktır.

Bu mantıkla yukarıdaki çalışmaya göz atarsak eğer “next” fonksiyonu çağrılmadığı için ilgili tetiklenen route çalıştırılmamıştır.

01020304050607080910const express = require("express");const app = express(); app.use((request, response, next) => {next();}); app.get("/", (request, response) => {response.send("Route çalıştı...");}).listen(5000);
Express.js - Middleware(Ara Katman) Nedir? Nasıl Kullanılır?

Bu şekilde “next” fonksiyonunu tetiklersek direkt olarak route tetiklenecektir.

Şimdi örneğimizi daha da derinleştirerek konumuzu detaylandırmak için bir kullanıcı oturum kontrolü sağlayalım.

010203040506070809101112131415161718const express = require("express");const app = express(); app.use((request, response, next) => {let isLogin = false;if (isLogin)next();elseresponse.send(${request.url} middleware çalıştı.<br> Kullanıcı girişi yapılmadı.);}); app.get("/", (request, response) => {response.send("Anasayfa");}).get("/profil", (request, response) => {response.send("Profil sayfası.");}).get("/ayarlar", (request, response) => {response.send("Ayarlar sayfası.");}).listen(5000, () => console.log("Yayın başladı..."));

Yukarıdaki kod bloğunu incelerseniz eğer “/”, “/profil” ve “/ayarlar” adreslerine olmak üzere üç adet route oluşturulmuştur. Bu routelara yapılan isteklerde middleware devreye girecek ve kullanıcı oturum kontrolü yapacaktır. Eğer oturumu açıksa ilgili sayfalara yönlendirecektir.

Express.js - Middleware(Ara Katman) Nedir? Nasıl Kullanılır?

Gördüğünüz gibi biz manuel olarak oturumu false değerinde tuttuğumuz için hiçbir route’a erişim gerçekleştirilememektedir.

Eğer ki bir middleware katmanının sade ve sadece istediğiniz bir route rotasında uygulanmasını istiyorsanız aşağıdaki gibi çalışma gerçekleştirebilirsiniz.

01020304050607080910111213...app.use("/profil", (request, response, next) => {let isLogin = false;if (isLogin)next();elseresponse.send(${request.url} middleware çalıştı.<br> Kullanıcı girişi yapılmadı.);});...
Express.js - Middleware(Ara Katman) Nedir? Nasıl Kullanılır?

“use” fonksiyonunun ilk parametresine hangi routeta middleware’ın çalışılmasını istiyorsanız belirtmeniz yeterlidir.

Ayrı Bir Modül Olarak Middleware

Middleware katmanını farklı bir modül olarak tasarlayarak ihtiyaca dönük gereken noktalarda require edebilir ve kullanabiliriz.

123456789//-isLogin.jsconst isLogin = (request, response, next) => {let isLogin = false;if (isLogin)next();elseresponse.send(${request.url} middleware çalıştı.<br> Kullanıcı girişi yapılmadı.);};module.exports = isLogin;

Yukarıda görüldüğü üzere modül olarak tasarlanan middleware katmanını aşağıdaki gibi require ederek kullanabiliriz.

123456789...const isLogin = require("./isLogin"); app.use(isLogin);...

Export edilen modülü require ile elde ettikten sonra “app.use” fonksiyonuna direkt olarak vermemiz yeterlidir.

Modül bazlı çalışırken istenilen route rotasında middleware katmanını kullanmak isterseniz eğer aşağıdaki gibi çalışabilirsiniz.

010203040506070809101112const express = require("express");const app = express();const isLogin = require("./isLogin");  app.get("/", isLogin, (request, response) => {response.send("Anasayfa");}).get("/profil", (request, response) => {response.send("Profil sayfası.");}).get("/ayarlar", isLogin, (request, response) => {response.send("Ayarlar sayfası.");}).listen(5000, () => console.log("Yayın başladı..."));

Görüldüğü üzere direkt olarak route fonksiyonlarında ikinci parametre olarak ilgili middleware modülünü vermemiz yeterlidir.

Eğer ki middleware modülleri birden fazla ise aşağıdaki gibi bir yaklaşım sergileyebilirsiniz.

01020304050607080910111213...const app = express();const isLogin = require("./isLogin");const control = require("./control"); app.get("/", isLogin, control, (request, response) => {response.send("Anasayfa");})...

Dikkat ederseniz eğer route rotasında ilk parametreden sonra istenildiği kadar middleware atanabilmektedir. Buradaki öncelik sıralaması atama sıralamasıyla birebir uyumludur. Yani ilk olarak “isLogin” middleware katmanı kontrol edilecek. Eğer “next” metodu tetiklenirse ardından “control” middleware katmanı denetlenecektir. Ve bu işlem atanan n adet katman için bu şekilde devam edecektir.

Bir yazımızın daha sonuna gelmiş bulunmaktayız. Umarım bol bol faydalanırsınız.

Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar dilerim…