Sefa Demirtaş

Sefa Demirtaş

#react

Promise nedir?

Promise nedir?
0 views
11 min read
#react

Promise nedir?

promise bir asenkron işleminin nihai sonucunu resolve veya başarısızlığını reject ifade eder.

Bu klavuz öncelikle promise kavramını tüketicilerin nasıl kullanabileceğine değinilecek ve daha sonra ise promise kavramının nasıl işlediğinden bahsedilecektir.

Senaryo bir blog web sitesinin var olan belli bir id si olan user kullanıcısının

  • user nesnesini özelliklerini
  • user nesnesinin postlarını
  • user nesnesinin post tuna yapılan commment yorumlarını listelemek istiyorum.

İşlemler axios kullanılacaktır. axios veri aktarım aracı olarak kullanılan bir javascript kütüphanesidir. Promise mantığı ile çalışır. Örnek olarak seçilme nedenide budur.

GİRİŞ

Web sitemizin backend kısmından öncelikle kullanıcın özelliklerini, sonra post ve bu postun comment lerini elde etmeye çalışalım.

index.js
import axios from "axios";
const getUserId = (userId) => {
  axios(`https://jsonplaceholder.typicode.com/users/${userId}`).then((data) =>
    console.log("User", data.data)
  );
};

const getUserPostId = (userId) => {
  axios(`https://jsonplaceholder.typicode.com/posts/${userId}`).then((data) =>
    console.log("Post", data.data)
  );
};

const getUserPostIdComment = (postId) => {
  axios(`https://jsonplaceholder.typicode.com/posts/${postId}/comments`).then(
    (data) => console.log("Comments", data.data)
  );
};

const createUser = (func1, func2, fun3) => {
  func1;
  func2;
  fun3;
};

createUser(getUserId(1), getUserPostId(1), getUserPostIdComment(1));

Bu yapı axios kütüphanesinin promise özelliğine sahip olması nedeni ile senkron harekat edecek ve user dan sonra post devamında final olarak commentsler beklenirken belirsiz bir akış ile bilgiler gelecektir. then ifadesi devamında açıklanacaktır.

Promis kullanarak bu fonsksiyonu yazmak istersek.

index.js
import axios from "axios";
const getUserId = async (userId) => {
  const { data: user } = await axios(
    `https://jsonplaceholder.typicode.com/users/${userId}`
  );
  return console.log("USER", user);
};

const getUserPostId = async (userId) => {
  const { data: post } = await axios(
    `https://jsonplaceholder.typicode.com/posts/${userId}`
  );
  return console.log("POST", post);
};

const getUserPostIdComment = async (postId) => {
  const { data: comments } = await axios(
    `https://jsonplaceholder.typicode.com/posts/${postId}/comments`
  );
  return console.log("COMMMENTS", comments);
};

const createUser = (data) => {
  return new Promise((resolve, reject) => {
    resolve(data);
    reject("Error");
  });
};

createUser()
  .then(() => getUserId(1))
  .then(() => getUserPostId(1))
  .then(() => getUserPostIdComment(1))
  .catch((e) => console.log(e));

Promise fonksiyonları olumlu değer olarak resolve veya hata olarak reject döner ancak mutlaka olumlu veya hatalı bir dönüş dönecektir. createUser fonksiyonunu Promise olarak tanımladık ve artık then kelime anahtaının kullanarak bir önceki işlemin gerçekleşme durumuna göre ikinci gerçekleşecektir. then bloğu return olarak mutlaka bir değer döndürmelidir. Diğer then bloğu değer döndürülmemesi durumunda istikrarsız çalışacaktır.

Promise bir işlemin diğer işleme bağlantılı olması durumunu ifade eder. Gerçekleşecek işlemi ifade eder. Eğer döngüde oluşacak hata diğer fonsiyonlar içinde ortak olura catch anahtar kelimesi ile yakalanabilir.

  • Promise ifadeleri bir önceki taahütün gerçekleşmesine bağlıdır. Eğer return edilmez ise net sonucu vermez.

Chaining(Zincirleme)

index.js
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};

const data = await doSomething("https://jsonplaceholder.typicode.com/posts/1")
  .then(async (url) => {
    const { data } = await axios(url);
    // return anaktar kelşmesi eksik.
  })
  .catch((e) => console.log(e));

console.log(data);
console
undefined

return anahtar kelimesi ile değer döndürül ise

index.js
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};

const data = await doSomething("https://jsonplaceholder.typicode.com/posts/1")
  .then(async (url) => {
    const { data } = await axios(url);
    return data;
  })
  .catch((e) => console.log(e));

console.log(data);
console
{
  userId: 1,
  id: 1,
  title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
  body: 'quia et suscipit\n' +
    'suscipit recusandae consequuntur expedita et cum\n' +
    'reprehenderit molestiae ut ut quas totam\n' +
    'nostrum rerum est autem sunt rem eveniet architecto'
}
  • İç içe promise ifadelerinin kullanılması durumunda geciklemeler olabileceğinden verilerde tutarlık olmayacaktır. listPostIdComments sonuç olarak [] sonucunu verebilir.
index.js
import axios from "axios";

const listPostIdComments = [];
const url = "https://jsonplaceholder.typicode.com/posts/1/comments";
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};
doSomething(url)
  .then((url) => {
    // return anahtar kelimesi eksik
    axios(url)
      .then((data) => listPostIdComments.push(...data.data))
      .then(() => {
        console.log(listPostIdComments);
      });
  })
  .catch((e) => console.log(e));
  • return ifadesi eklenmelidir.
index.js
import axios from "axios";

const listPostIdComments = [];
const url = "https://jsonplaceholder.typicode.com/posts/1/comments";
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};
doSomething(url)
  .then((url) => {
    return axios(url)
      .then((data) => listPostIdComments.push(...data.data))
      .then(() => {
        console.log(listPostIdComments);
      });
  })
  .catch((e) => console.log(e));
  • Aynı sonuca async/await kullanılarakta ulaşılabilir.
index.js
import axios from "axios";
const listPostIdComments = [];
const url = "https://jsonplaceholder.typicode.com/posts/1/comments";
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};
const logIngredients = async (url) => {
  const urlText = await doSomething(url);
  const { data } = await axios(urlText);
  listPostIdComments.push(data);
  console.log(listPostIdComments);
};

logIngredients(url);

async/await kullanılırken async bir fonksiyonun await olarak bekletilen eşzamansız işlevin sonucu bellenir. Eğer await kullnılmamış eşzamansız işlem var ise o işlevine devam eder.

Error handling(Hata Yönetimi)

index.js
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);

import axios from "axios";

const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};

const data = await doSomething("https://jsonplaceholder.typicode.com/posts/1")
  .then(async (url) => {
    const { data } = await axios(url);
    console.log(data);
    return data;
  })
  .catch((e) => console.log(e));
  • Her then ifadesi bir işlevsel fonksiyonu ve hata fonksiyonunu barındırır. Ancak ortak bir hata var ise catch ifadesi ile hata yakalanır.

  • async/await kullanılacak ise try/catch kullanılabilir.

index.js
import axios from "axios";
const listPostIdComments = [];
const url = "https://jsonplaceholder.typicode.com/posts/1/comments";
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};
const logIngredients = async (url) => {
  try {
    const urlText = await doSomething(url);
    const { data } = await axios(urlText);
    listPostIdComments.push(data);
    console.log(listPostIdComments);
  } catch (e) {
    console.log(e);
  }
};

logIngredients(url);

Nesting

Posta ait commentleri listelediğimiz zaman then bloğu içerisinde bulunan başkabir promise yapsısı olan axios ile veri çekmiştik. Spesifik olarak, iç içe geçmiş bir yakalama yalnızca kendi kapsamındaki ve altındaki hataları yakalar, iç içe kapsamın dışındaki zincirde daha üstteki hataları değil. Doğru kullanıldığında bu hata yöntemi daha fazla hassasiyet sağlar.

index.js
import axios from "axios";

const listPostIdComments = [];
const url = "https://jsonplaceholder.typicode.com/posts/1/comments";
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};
doSomething(url)
  .then((url) =>
    axios(url)
      .then((data) => listPostIdComments.push(...data.data))
      .then(() => {
        console.log(listPostIdComments);
      })
      .catch((e = console.log(e)))
  )
  .catch((e) => console.log(e));

(Chaining after a catch) Bir yakalamanın ardından zincirleme

  • catch anahtar gelimesinden sonrada taahütte bulunabilirsiniz. then işlem başarısız olsa bile başka taahütlerini gerçekleştirebilir.
index.js
import axios from "axios";

const listPostIdComments = [];
const url = "https://jsonplaceholder.typicode.com/users/1";
const doSomething = (url) => {
  return new Promise((resolve, reject) => {
    resolve(url);
    reject("Error");
  });
};
doSomething(url)
  .then((url) => {
    return axios(url)
      .then((data) => listPostIdComments.push(data.data))
      .then(() => {
        console.log(listPostIdComments);
      });
  })
  .catch((e) => console.log(e))
  .then(() => console.log("Catch bloğundan sonrada çalışırım"));

Promise

Diğer başlıklar promise işlevlerinin nasıl kullanılabileceği yani tüketimi ile alakalı olarak nasıl bir kullanım sağlanır onlara değindik. Şimdi ise promise kavramını derinlemesine inceleyeceğim.e

Promise bir vaadin gerçekleşmesinin sonucunda değeri veya çeşitli nedenlerden denedi ile gerçekleşmemesi(hata) durumudur. *Promise** oluşturulan her değeri hemen döndürmek yerine, gelecekte oluşturulan değeri sağlanmsını taahüd eder.

Promise durumları;

  • **pending:**Başlangıç durumu, işlem ne yerine getirildi nede reddedildi.
  • **fulfilled:**İşlemin başarı ile yerine getirildiğini ifade eder.
  • **rejected:**İşlemin başarısız ollduğu anlamına gelir.
Image

Promise olarak ele alınan işlem asenkron işlemlerin.

.then() Metodu en fazla iki bağımsız değişken alır; ilk argüman, sözün yerine getirilmiş durumu için bir geri çağırma işlevidir (reselvo) ve ikinci argüman, reddedilen durum için bir geri çağırma işlevidir (reject). Her biri .then(), isteğe bağlı olarak zincirleme için kullanılabilen yeni oluşturulmuş bir söz nesnesini döndürür.

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 300);
});

myPromise
  .then(handleFulfilledA, handleRejectedA)
  .then(handleFulfilledB, handleRejectedB)
  .then(handleFulfilledC, handleRejectedC);

Yukarıdaki örnekte her then() bloğu içinde işlemin başarılı durumunu belirten handleFulfilledA(resolve), hata durumunda işlenecek hatalarla birlikte verilmiştir(handleRejectedA).

index.js
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 300);
});

const mydata = await myPromise
  .then((data) => {
    console.log(data);
    return data;
  })
  .then((data) => {
    console.log(data);
    return data;
  })
  .then((data) => {
    console.log(data);
    return data;
  });

console.log("Mydata : ", mydata);
console

foo
foo
foo
Mydata :  foo

Not: Daha hızlı yürütme için, tüm senkronize eylemlerin tercihen tek bir işleyicide yapılması gerekir, aksi takdirde tüm işleyicilerin sırayla yürütülmesi birkaç onay işareti gerektirecektir. catch ve arrow functions

index.js
myPromise
  .then((value) => `${value} and bar`)
  .then((value) => `${value} and bar again`)
  .then((value) => `${value} and again`)
  .then((value) => `${value} and again`)
  .then((value) => {
    console.log(value);
  })
  .catch((err) => {
    console.error(err);
  });

promise yapısında döndrülen başarılı bir dönüş tekrar başka bir promise olarak kullanılabilir. Bu durum tekrar .then() metodunun çağrılabileceği ve/veya çağrılması gerektiği anlamına gelir.

index.js
const promiseA = new Promise(myExecutorFunc);
const promiseB = promiseA.then(handleFulfilled1, handleRejected1);
const promiseC = promiseA.then(handleFulfilled2, handleRejected2);
  • Promise.all() Tüm sözler yerine getirildiğinde yerine getirilir ; vaatlerden herhangi biri reddedildiğinde reddeder .

  • Promise.allSettled() Tüm sözler yerine getirildiğinde yerine getirilir .

  • Promise.any() Verilen sözlerden herhangi biri yerine getirildiğinde yerine getirilir ; tüm vaatler reddedildiğinde reddeder .

  • Promise.race() Verilen sözlerden herhangi biri yerine getirildiğinde yerleşir . Başka bir deyişle, sözlerden herhangi biri yerine getirildiğinde yerine getirilmiş olur; vaatlerden herhangi biri reddedildiğinde reddeder.

  • Promise.reject() PromiseBelirtilen nedenle reddedilen yeni bir nesneyi döndürür .

  • Promise.resolve() PromiseVerilen değerle çözümlenen bir nesneyi döndürür . Eğer değer o zaman mümkünse (yani bir thenyöntemi varsa), iade edilen söz, o zaman mümkün olanı "takip edecek" ve nihai durumunu benimseyecektir; aksi halde iade edilen söz değeriyle yerine getirilmiş olacaktır.

  • Promise.withResolvers() PromiseYapıcının yürütücüsüne iletilen iki parametreye karşılık gelen, yeni bir nesne ve onu çözümlemek veya reddetmek için iki işlev içeren bir nesne döndürür Promise().

Gelişmiş Örnek

index.js
// Hata işlemeyi denemek için "threshold" değerleri rastgele hatalara neden olur

const THRESHOLD_A = 8; // hatayı garanti etmek için sıfır 0 kullanılabilir

function tetheredGetNumber(resolve, reject) {
  setTimeout(() => {
    const randomInt = Date.now();
    const value = randomInt % 10;
    if (value < THRESHOLD_A) {
      resolve(value);
    } else {
      reject(`Too large: ${value}`);
    }
  }, 500);
}

function determineParity(value) {
  const isOdd = value % 2 === 1;
  return { value, isOdd };
}

function troubleWithGetNumber(reason) {
  const err = new Error("Trouble getting number", { cause: reason });
  console.error(err);
  throw err;
}

function promiseGetWord(parityInfo) {
  return new Promise((resolve, reject) => {
    const { value, isOdd } = parityInfo;
    if (value >= THRESHOLD_A - 1) {
      reject(`Still too large: ${value}`);
    } else {
      parityInfo.wordEvenOdd = isOdd ? "odd" : "even";
      resolve(parityInfo);
    }
  });
}

new Promise(tetheredGetNumber)
  .then(determineParity, troubleWithGetNumber)
  .then(promiseGetWord)
  .then((info) => {
    console.log(`Got: ${info.value}, ${info.wordEvenOdd}`);
    return info;
  })
  .catch((reason) => {
    if (reason.cause) {
      console.error("Had previously handled error");
    } else {
      console.error(`Trouble with promiseGetWord(): ${reason}`);
    }
  })
  .finally((info) => console.log("All done"));
  • Promise işlem tanımlanır. tetheredGetNumber value random değeri THRESHOLD_A feğerinden büyük ise hata olarak troubleWithGetNumber aynı zamanda catch bloğu devreye girer. Diğer than bloklarında ise hata cath bloğu devreye alınır. finally bloğu her durumda çalışan blogdur.

> promise-nedir@1.0.0 start
> node index

8
Got: 1, odd
All done
❯ npm start

> promise-nedir@1.0.0 start
> node index

8
Got: 2, even
All done
❯ npm start

> promise-nedir@1.0.0 start
> node index

8
Error: Trouble getting number
    at troubleWithGetNumber (file:///Users/sefademirtas/Desktop/react-note/promise-nedir/index.js:162:17) {
  [cause]: 'Too large: 9'
}
Had previously handled error
All done
index.html
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Time right now:</title>
  </head>

  <body>
    <button id="make-promise">Make a promise!</button>
    <div id="log"></div>
  </body>
  <script src="./index.js"></script>
</html>
index.js
"use strict";

let promiseCount = 0;

function testPromise() {
  const thisPromiseCount = ++promiseCount;
  const log = document.getElementById("log");
  // başlangıç
  log.insertAdjacentHTML("beforeend", `${thisPromiseCount}) Started<br>`);
// Yeni bir söz veriyoruz: Bu sözün sayısal olarak sayılacağına söz veriyoruz,
// 1'den başlayarak (3sn bekledikten sonra)
  const p1 = new Promise((resolve, reject) => {
// Yürütücü fonksiyon yetenekle çağrılır
// vaadi çözmek veya reddetmek için
    log.insertAdjacentHTML(
      "beforeend",
      `${thisPromiseCount}) Promise constructor<br>`
    );
// Bu sadece asenkronizm oluşturmaya yönelik bir örnektir    setTimeout(() => {
// Sözümüzü yerine getiriyoruz
      resolve(thisPromiseCount);
    }, Math.random() * 2000 + 1000);
  });

// Then() çağrısı ile söz çözümlendiğinde ne yapacağımızı tanımlıyoruz,
// ve catch() çağrısıyla söz reddedildiğinde ne yapılması gerektiği
  p1.then((val) => {

// Yerine getirme değerini günlüğe kaydet
    log.insertAdjacentHTML("beforeend", `${val}) Promise fulfilled<br>`);
  }).catch((reason) => {
// Reddedilme nedenini günlüğe kaydedin    console.log(`Handle rejected promise (${reason}) here.`);
  });
  // son
  log.insertAdjacentHTML("beforeend", `${thisPromiseCount}) Promise made<br>`);
}

const btn = document.getElementById("make-promise");
btn.addEventListener("click", testPromise);
Image