Promise Hell-ის პრობლემა JavaScript-ში

თქვენ უკვე იცით, რომ პრომისები შეიქმნა იმისთვის, რომ გადაეჭრათ callback hell-ის პრობლემა. თუმცა, დროთა განმავლობაში აღმოჩნდა, რომ პრომისებსაც შეუძლიათ გამოიწვიონ რთული კოდი. ეს პრობლემა ანალოგიით დაერქვა promise hell.

მოდით განვიხილოთ ეს პრობლემა კოდის მაგალითებზე. დავუშვათ, გვაქვს ფუნქცია getSmth, რომელიც იღებს პარამეტრს და აბრუნებს შედეგს ამ პარამეტრის მიხედვით:

javascriptfunction getSmth(num) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num * num), 1000)
  });
}

ამ შემთხვევაში ჩვენ ვიმიტირებთ რაიმე სასარგებლო ოპერაციას (მაგალითად, სერვერიდან მონაცემების მიღებას). იმიტირებისთვის ჩვენ უბრალოდ პარამეტრად ვაწვდით რიცხვს და ერთი წამის შემდეგ ვაბრუნებთ ამ რიცხვის კვადრატს.

მოდით ახლა გამოვიყენოთ ჩვენი ფუნქცია getSmth სხვა ფუნქციის შიგნით:

javascriptfunction func() {
  getSmth(2).then(res => {
    console.log(res); // გამოიტანს 4-ს
  });
}

func();

პირველი პრობლემა

ერთმანეთის მიყოლებით განლაგებული then კონსტრუქციები ართულებს კოდის გაგებას:

javascriptfunction func(){
  getSmth(2).then(res1 => {
    // ვაკეთებთ რაღაცას
  }).then(res2 => {
    // ვაკეთებთ რაღაცას
  }).then(res3 => {
    // ვაკეთებთ რაღაცას
  }).then(res4 => {
    // ვაკეთებთ რაღაცას
  }).then(res5 => {
    // ვაკეთებთ რაღაცას
  }).then(res6 => {
    // ვაკეთებთ რაღაცას
  });
}

func();

მეორე პრობლემა

არსებობს სხვა ხასიათის პრობლემაც. დავუშვათ ახლა გვსურს ჩვენი ფუნქციის ორჯერ გამოყენება, შემდეგ კი შედეგების შეკრება. შედეგად ჩვენ მივიღებთ ასეთ კოდს:

javascriptfunction func() {
  getSmth(2).then(res1 => {
    getSmth(3).then(res2 => {
      console.log(res1 + res2); // გამოიტანს 13-ს
    });
  });
}

func();

უკვე წააგავს callback hell-ს, არა? დავამატოთ კიდევ ერთი ფუნქციის გამოძახება - კოდი გაუარესდება:

javascriptfunction func() {
  getSmth(2).then(res1 => {
    getSmth(3).then(res2 => {
      getSmth(4).then(res3 => {
        console.log(res1 + res2 + res3);
      });
    });
  });
}

func();

შესაძლებელია, რა თქმა უნდა, გამოვიყენოთ Promise.all:

javascriptfunction func() {
  Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
    console.log(res[0] + res[1] + res[2]);
  });
}

func();

თუმცა, მივიღეთ თუ არა იგივე? არა! პირველ შემთხვევაში ყოველი ახალი ფუნქცია ელოდება წინა პრომისის დასრულებას, ხოლო მეორე შემთხვევაში - ყველა პრომისი სრულდება ერთდროულად. ეს განსხვავება მნიშვნელოვანი იქნება იმ შემთხვევაში, როდესაც ჩვენ მომდევნო ფუნქციას გვსურს გადავცეთ წინახის გამოძახების შედეგი:

javascriptfunction func() {
  getSmth(2).then(res1 => {
    getSmth(res1).then(res2 => {
      getSmth(res2).then(res3 => {
        console.log(res3);
      });
    });
  });
}

func();