Betül SARAL

Bilgisayar Mühendisi

Node.js - Promises

| Comments

Promises, Node.js gibi asenkron çalışma mantığını kullanan programlamalar için önemli bir yöntemdir. Pyramid of Doom olarak nitelendirilen iç içe geçmiş karmaşık ve uzun kodların daha düzenli ve daha sade hale gelmesini sağlar. Bu yöntem belki tek başına kullanılan asenkron bir fonksiyon için çok etkili değil ama birden fazla fonksiyon olma durumunda kullanılması gereken bir yöntemdir.

Promises için birçok kütüphane bulunur. Bunlardan en çok bilineni Blubird ve Q kütüphanesidir. Node.js kullanan birçok framework de aslında promises yapısını kullanılan kütüphaneler eklidir. Mesela benim şu an kullandığım Sails.js veritabanı sorguları için promise yapısı olarak bluebird ile çalışabilmektedir.

Şimdi promise yapısı kullanmadan iç içe geçmiş küçük bir programlama yapalım. setTimeout olarak farklı milisaniyelerde çalışan 4 adet fonksiyon tanımlıyoruz.

Pyramid of Doom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
function testFunc1(name,callback) {
    setTimeout(function () {
        callback(null,name);
    }, 500);
}

function testFunc2(name,callback) {
    setTimeout(function () {
        callback(null,name)
    }, 100);
}

function testFunc3(name,callback) {
    setTimeout(function () {
        callback(null,name)
    }, 900);
}

function testFunc4(name,callback) {
    setTimeout(function () {
        callback(null,name)
    }, 3000);
}

testFunc1("Betül",function(err,result1){
    if(err){
        console.log(err);
    }
    else{
        console.log("testFunc1 sonucu : "+result1);
        testFunc2("Hande",function(err,result2){
            if(err){
                console.log(err);
            }
            else{
                console.log("testFunc2 sonucu : "+result2);
                testFunc3("Tuğba",function(err,result3){
                    if(err){
                        console.log(err);
                    }
                    else{
                        console.log("testFunc3 sonucu : "+result3);
                        testFunc4("Yasemin",function(err,result4){
                            if(err){
                                console.log(err);
                            }
                            else{
                                console.log("testFunc4 sonucu : "+result4);
                            }
                        });
                    }
                });
            }
        });
    }
});

Bu şekilde 10 tane daha fonksiyon çalıştırdığınızı düşünün. Hepsi iç içe. Ne kadar kötü gözüküyor değil mi ? Ama promises ile çalıştığımız zaman bu problemi ortadan kaldırıyoruz.

Ben Q kütüphanesini kullandım. Siz isterseniz blubird kullanabilirsiniz. Çalışma mantıkları aynı ama söz dizimleri birbirine benzemiyor. Q kütüphanesini npm ile burdan yükleyebilirsiniz.

promise.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
var Q = require('q');

function testFunc1(name) {
	var deferred = Q.defer();
	setTimeout(function () {
	    deferred.resolve("test1 fonksiyonu : "+name);
	}, 500);

	return deferred.promise;
}

function testFunc2(name) {
    var deferred = Q.defer();

    setTimeout(function () {
        deferred.resolve("test2 fonksiyonu : "+ name);
    }, 100);

    return deferred.promise;
}

function testFunc3(name) {
 	var deferred = Q.defer();

    setTimeout(function () {
        deferred.resolve("test3 fonksiyonu : "+name);
    }, 900);

    return deferred.promise;
}

function testFunc4(name) {
 	var deferred = Q.defer();

    setTimeout(function () {
        deferred.resolve("test4 fonksiyonu : "+name);
    }, 300);

    return deferred.promise;
}

testFunc1("Betül")
    .then(function (result) {
        console.log(result);
        // testFunc2 fonksiyonunu çağırıyoruz
        return testFunc2("Hande");
    })
    .then(function (result) {

       console.log(result);

        // testFunc3 fonksiyonunu çağırıyoruz
        return testFunc3("Tuğba");
    })
    .then(function (result) {
        console.log(result);

        // testFunc4 fonksiyonunu çağırıyoruz
        return testFunc4("Yasemin");
    })
    .then(function (result) {
    	//testFunc4 fonksiyonunu sonucu
        console.log(result);
    })
    .catch(function (error) {
        console.log("Hata : "+error);
    });

deferred ile promises nesnemizi tanımlıyoruz. then ve catch ile fonksiyon sonucunda oluşan nesnemizi döndürüyoruz. Promises yapısında callback kullanılmaz. Bunun yerine fonksiyon sonuçları senkron bir şekilde then , catch yapısına gider. Eğer fonksiyon sonucu bir hata oluşmuyorsa then fonksiyonuna, eğer bu fonksiyonlardan herhangi birinden hata alıyorsak ise catch fonksiyonuna gider. Böylece her bir fonksiyon için hata kontrolü yapmak yerine catch kullanarak hata kontrolünü tüm fonksiyonlar için tek bir satırda yapıyoruz.

Şimdilik bu kadar. Promises ile ilgili araştırmalarım devam ediyor. Yeni şeyler öğrendikçe burayı da güncellemeye çalışacağım.

Comments