Problem w zrozumieniu obietnic

0

Witam wszystkich serdecznie,

Napisałem sobie taki testowy kod, żeby zrozumieć działanie Promise.all. Efekt który chce uzyskać to objąć serię funkcji asynchronicznych Promise.all i po spełnieniu wykonać jeszcze raz tą serię. Docelowo w pętli wiele razy. Mam problem w zrozumieniu działania nastepującego kodu:

async function opoznioneWyswietlanie(time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("przekazany czas:" + time)
    }, time);
  })
}

async function seria(nazwaserii, dodatkowyCzas) {
  let zwrot1 = await opoznioneWyswietlanie(1000+dodatkowyCzas);
  console.log("zwrot1: " + zwrot1);
  let zwrot2 = await opoznioneWyswietlanie(200 + dodatkowyCzas);
  console.log("zwrot2: " + zwrot2);
  return new Promise((resolve => {
    resolve(`zakonczona seria: ${nazwaserii}`)
  }))
}

const funkcjeAsynchroniczne = [seria("seriaPiersza",100), seria("seriaDruga",400)];

const sekwencyjnie = async function () {
  for (const elem of funkcjeAsynchroniczne) {
    var odp = await elem;
    console.log(odp);
  }
  for (const elem of funkcjeAsynchroniczne) {
    var odp = await elem;
    console.log(odp);
  }
}

const rownolegle = async function(){
  let odp = await Promise.all(funkcjeAsynchroniczne)
  console.log("Spełniona seria obietnic #1: "+odp);
  let odp2 = await Promise.all(funkcjeAsynchroniczne)
  console.log("Spełniona seria obietnic #2: " + odp2);
  let odp3 = await Promise.all(funkcjeAsynchroniczne)
  console.log("Spełniona seria obietnic #3: " + odp3);
}

// sekwencyjnie();
rownolegle();

Zrobiłem 2 warianty wywołania serii funkcji z tablicy funkcjeAsynchroniczne. Jedno zadanie po drugim 2 razy (funkcja sekwencyjnie) i wszystkie zadania rownolegle za pomocą Promise.all 3 razy (funkcja rownlolegle). Nie rozumiem dlaczego po pierwszej serii wywołań funkcja opoznioneWyswietlanie nie jest wywoływana. W każdym przypadku wywołuje się 4 razy a spodziewałem się, że odpowiednio dla sekwencyjnie(); wywoła się 8 razy, a dla rownlolegle(); 12 razy. Wszystkie obietnice zostają wypełnione z wyjątkiem tych z funkcji opoznioneWyswietlanie. Ktos potrafi to wyjaśnić ?

1

funkcje wywołujesz w tej linijce :

const funkcjeAsynchroniczne = [seria("seriaPiersza",100), seria("seriaDruga",400)];

czyli masz tablice składająca się z dwóch promisów, nie z dwóch funkcji do wywołania, czyli dalej te Twoje serie operują na tych samych promisach. Czyli w tym wywołaniu równoległym, nie wywołujesz trzy razy tych funkcji z tablicy (bo ich tam nie ma), tylko trzy razy czekasz na te same dwa promisy, co nie ma sensu.

jak żyć pytasz? zmieniając powyższą linijkę na:

const funkcjeAsynchroniczne = () => [seria("seriaPiersza",100), seria("seriaDruga",400)];

a potem

let odp = await Promise.all(funkcjeAsynchroniczne)

na i resztę analogicznie

let odp = await Promise.all(funkcjeAsynchroniczne())

kod zacznie robić to co chcesz :


async function opoznioneWyswietlanie(time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("przekazany czas:" + time)
    }, time);
  })
}

async function seria(nazwaserii, dodatkowyCzas) {
  let zwrot1 = await opoznioneWyswietlanie(1000+dodatkowyCzas);
  console.log("zwrot1: " + zwrot1);
  let zwrot2 = await opoznioneWyswietlanie(200 + dodatkowyCzas);
  console.log("zwrot2: " + zwrot2);
  return new Promise((resolve => {
    resolve(`zakonczona seria: ${nazwaserii}`)
  }))
}

const funkcjeAsynchroniczne = () => [seria("seriaPiersza",100), seria("seriaDruga",400)];

const sekwencyjnie = async function () {
  for (const elem of funkcjeAsynchroniczne) {
    var odp = await elem;
    console.log(odp);
  }
  for (const elem of funkcjeAsynchroniczne) {
    var odp = await elem;
    console.log(odp);
  }
}

const rownolegle = async function(){
  let odp = await Promise.all(funkcjeAsynchroniczne())
  console.log("Spełniona seria obietnic #1: "+odp);
  let odp2 = await Promise.all(funkcjeAsynchroniczne())
  console.log("Spełniona seria obietnic #2: " + odp2);
  let odp3 = await Promise.all(funkcjeAsynchroniczne())
  console.log("Spełniona seria obietnic #3: " + odp3);
}

// sekwencyjnie();
rownolegle();

0

Piękne dzięki, przywróciłeś mi sens życia, bo 4 dni nie mogłem znaleźć przyczyny. Zupełnie przeoczyłem fakt, że w deklaracji tablicy funkcjeAsynchroniczne już te funkcje sie wywołują, a ja tak naprawdę miałem zamiar przechowywać tam tylko dane do wywołania tych funkcji i wywoływać je dopiero później w pętli for..of. Twoje rozwiązanie jest najbardziej eleganckie, ale na próbę zrobiłem też po mojemu ( troche okrężnie), żeby upewnić sie ze zrozumiałem błąd i tez śmiga:

async function opoznioneWyswietlanie(time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("przekazany czas:" + time)
    }, time);
  })
}

async function seria(nazwaserii, dodatkowyCzas) {
  let zwrot1 = await opoznioneWyswietlanie(1000+dodatkowyCzas);
  console.log("zwrot1: " + zwrot1);
  let zwrot2 = await opoznioneWyswietlanie(200 + dodatkowyCzas);
  console.log("zwrot2: " + zwrot2);
  return new Promise((resolve => {
    resolve(`zakonczona seria: ${nazwaserii}`)
  }))
}

const funkcjeAsynchroniczne = [
  [seria,"seriaPierwsza",100],
  [seria,"seriaDruga",400],
  [seria,"seriaTrzecia",600]
  ];

const sekwencyjnie = async function () {
  for (const elem of funkcjeAsynchroniczne) {
    console.log(elem[1]);
    const odp = await elem[0](elem[1],elem[2]);
    console.log(odp);
  }
  for (const elem of funkcjeAsynchroniczne) {
    var odp = await elem[0](elem[1],elem[2]);
    console.log(odp);
  }
}

const rownolegle = async function(){
  let odp = await Promise.all(funkcjeAsynchroniczne.map(elem => elem[0](elem[1],elem[2])))
  console.log("Spełniona seria obietnic #1: "+odp);
  let odp2 = await Promise.all(funkcjeAsynchroniczne.map(elem => elem[0](elem[1],elem[2])))
  console.log("Spełniona seria obietnic #2: " + odp2);
  let odp3 = await Promise.all(funkcjeAsynchroniczne.map(elem => elem[0](elem[1],elem[2])))
  console.log("Spełniona seria obietnic #3: " + odp3);
}

sekwencyjnie();
// rownolegle();

Mała ciekawostka - sprawdzałem sobie ten kod na szybko w jsbin.com i przy wywołaniu sekwencyjnie(); pętla for..off nie iterowała po wszystkich elementach tablicy. Już miałem prosić o pomoc, a okazało się, że chyba z tym playgroundem jest coś nie tak bo w codepen.io i playcode.io działa jak trzeba. Jeszcze raz dzięki za pomoc !

1 użytkowników online, w tym zalogowanych: 0, gości: 1