Vinnaren i pepparkakshustävlingen!
  • 1
  • 2
2017-02-10, 01:08
  #1
Medlem
svettigafettsvinets avatar
Finns det någon här som förstår sig på promises i Javascript som kunde förklara hur de fungerar?

Vad händer i nedanstående kod t.ex.?


Kod:
function sleep(time) {
    return new Promise(resolve => {
        setTimeout(resolve, time)
		//resolve;
    })
}

var timeA = 3000;
var timeB = 1000;
var timeC = 500;

sleep(timeA).then(() => {
	
    console.log('a')
    return sleep(timeB);
}).then(() => {
    console.log('b')
    return sleep(timeC)
}).then(() => {
    console.log('c')
})
Citera
2017-02-10, 02:00
  #2
Medlem
svettigafettsvinets avatar
koden ovan kan skrivas om på följande vis om man använder function istället för ny => syntax.

Kod:
function sleep(time) {
    return new Promise(function(resolve){
        setTimeout(resolve, time)
		//resolve;
    })
}

var timeA = 3000;
var timeB = 1000;
var timeC = 500;

sleep(timeA).then(function(){
	
    console.log('a')
    return sleep(timeB);
}).then(function(){
    console.log('b')
    return sleep(timeC)
}).then(function(){
    console.log('c')
})
Citera
2017-02-10, 22:03
  #3
Medlem
Povels avatar
  • Du har en funktion `sleep` som returnerar ett promise.
  • När promiset resolve-ar (vilket är dess enda möjliga fulfillment i ditt exempel) utförs din `then`-handler (som du själv kopplar på direkt efter).
  • I de två första sådana returnerar du då nya promises, som på samma sätt hanteras av nästföljande `then`.
/p
Citera
2017-02-11, 14:25
  #4
Medlem
svettigafettsvinets avatar
Det jag egentligen behöver lösa är att jag vill kunna jobba synkront.

T.ex. jag hämtar en sak från en databas eller liknande med en metod i steg 1. Men i och med att javascript är asynkront så börjar den på steg2 innan steg1 är färdig och värdena hämtade vilket resulterar i errors. Detta måste vara ett oerhört vanligt problem som måste ha någon sorts standardlösning.
Citera
2017-02-11, 15:14
  #5
Medlem
Brunbeverns avatar
Citat:
Ursprungligen postat av svettigafettsvinet
Det jag egentligen behöver lösa är att jag vill kunna jobba synkront.

T.ex. jag hämtar en sak från en databas eller liknande med en metod i steg 1. Men i och med att javascript är asynkront så börjar den på steg2 innan steg1 är färdig och värdena hämtade vilket resulterar i errors. Detta måste vara ett oerhört vanligt problem som måste ha någon sorts standardlösning.

Det är ju just det som inte händer dock när du arbetar med promises. Om du utför någon asynkron operation för att sedan inom then() hantera resultat, så vet du ju att steg 2 körs efter steg 1 är färdig.

Du får nog förtydliga lite vad du menar.
Citera
2017-02-11, 22:24
  #6
Medlem
Mia-Rovys avatar
Citat:
Ursprungligen postat av svettigafettsvinet
Det jag egentligen behöver lösa är att jag vill kunna jobba synkront.
Om du vill att hela din applikation ska frysa sig när du hämtar data från externa källor så är promises vad du inte ska använda.

Om du vill att applikationen ska fungera som vanligt även när data hämtas så behöver du jobba asynkront. Detta är inget specifikt för javascript, utan gäller för alla språk.

Citat:
Ursprungligen postat av svettigafettsvinet
Men i och med att javascript är asynkront
Javascript är inte asynkront. Men det tillåter dig att jobba asynkront om du vill. Likt de flesta andra språk

Citat:
Ursprungligen postat av svettigafettsvinet
T.ex. jag hämtar en sak från en databas eller liknande med en metod i steg 1. Men i och med att javascript är asynkront så börjar den på steg2 innan steg1 är färdig och värdena hämtade vilket resulterar i errors. Detta måste vara ett oerhört vanligt problem som måste ha någon sorts standardlösning.
Du har två alternativ:
1. Jobba synkront. Alltså frys hela applikationen så att den inte går att använda medan data hämtas.
2. Jobba asynkront. Alltså fortsätt att köra alla andra funktioner medan data hämtas.

Standardlösningen är att jobba asynkront. Ofta via den Promises, som är helt okej.

Om du vill att steg2 ska utföras först när steg1 är klart så sätter du det i Promisets then-funktion
Citera
2017-02-12, 17:39
  #7
Medlem
svettigafettsvinets avatar
Citat:
Ursprungligen postat av Mia-Rovy
Om du vill att hela din applikation ska frysa sig när du hämtar data från externa källor så är promises vad du inte ska använda.

Om du vill att applikationen ska fungera som vanligt även när data hämtas så behöver du jobba asynkront. Detta är inget specifikt för javascript, utan gäller för alla språk.

Jag behöver kedja metoder så att metod 2 inte utförs innan metod 1 är färdig precis vad som är normalt i de flesta andra språk. Det är inte jätteuppenbart för mig när man faktiskt behöver använda dessa promises. Låt oss säga:

Kod:
let gris=komplicerad_funktion();

alert(gris); 

Hur lång tid behöver komplicerad_funktion ta innan javascript går till nästa steg och alert gris visar ett odefinierat värde? Det är ju inget som händer i vanliga fall.
Citera
2017-02-12, 17:54
  #8
Medlem
Mia-Rovys avatar
Citat:
Ursprungligen postat av svettigafettsvinet
Jag behöver kedja metoder så att metod 2 inte utförs innan metod 1 är färdig precis vad som är normalt i de flesta andra språk. Det är inte jätteuppenbart för mig när man faktiskt behöver använda dessa promises. Låt oss säga:

Kod:
let gris=komplicerad_funktion();

alert(gris); 

Hur lång tid behöver komplicerad_funktion ta innan javascript går till nästa steg och alert gris visar ett odefinierat värde? Det är ju inget som händer i vanliga fall.
Det är inte tid som är avgörande, det är djupet på funktionerna. Som i alla andra språk.

gris kommer aldrig att vara odefinierad så länge kompicerad_funktion returnerar något. Värdet på gris är synkront.

Först anropas funktionen. Sedan sparas värdet i variabeln. Som i alla språk.

Du missuppfattar någonting. JavaScript är inte "mer" eller "mindre" askynkront än något annat språk. Det du säger "gäller för de flesta andra språk" gäller även för javascript.

Om det förvirrar dig så låtsas att du skriver i ett annat språk. För det är ingen skillnad sett till när saker och ting utförs.

Promises är bara ett par funktioner som underlättar askynkront arbete. Finns i massa språk. Promises är varken någonting som man måste använda eller som definierar JavaScript på något sätt.


Du kanske ska använda vanliga callbacks om du vill jobba asynkront men inte gillar promises?
__________________
Senast redigerad av Mia-Rovy 2017-02-12 kl. 18:04.
Citera
2017-02-12, 18:03
  #9
Medlem
svettigafettsvinets avatar
Citat:
Ursprungligen postat av Mia-Rovy
Det är inte tid som är avgörande, det är djupet på funktionerna. Som i alla andra språk.

gris kommer aldrig att vara odefinierad så länge kompicerad_funktion returnerar något. Värdet på gris är synkront.

Det var ju intressant. Men om komplicerad_funktion inte returnerar utan sätter en global viabel så kan den alltså gå vidare innan den är satt och den globala variabel vara odefinierad i nästa steg. Vad händer om kompicerad_funktion gör en databasanslutning och hämtar värden i 30 sekunder kommer den ändå inte gå vidare om funktionen har en return?
Citera
2017-02-12, 18:12
  #10
Medlem
Mia-Rovys avatar
Citat:
Ursprungligen postat av svettigafettsvinet
Det var ju intressant. Men om komplicerad_funktion inte returnerar utan sätter en global viabel så kan den alltså gå vidare innan den är satt och den globala variabel vara odefinierad i nästa steg.
Nej, inte om den sätter den globala variabeln i samma "djup". Om du däremot någonstans sätter den globala variabeln i ett callback (eller Promise, som är callbacks med hjälpverktyg)

Citat:
Ursprungligen postat av svettigafettsvinet
Vad händer om kompicerad_funktion gör en databasanslutning och hämtar värden i 30 sekunder kommer den ändå inte gå vidare om funktionen har en return?
Det beror helt och hållet på om databasanslutningen och timern är sykron eller asynkron

Detta är fula exempel som jag inte orkar validera eller testa, men såhär kan olika timers se ut. De funkar säkert inte men du fattar säkert:
Kod:
syncSec = sec => {
  end = nowInSeconds() + sec;
  while(nowInSeconds() <= end) {
    
  }
  return 'Klar!';
}

asyncSec = sec, callback => {
  end = nowInSeconds() + sec;
  if(nowInSeconds() >= end) {
    asyncSec(sec, callback);
  } else {
    callback('klar!')
  }
}
__________________
Senast redigerad av Mia-Rovy 2017-02-12 kl. 18:29.
Citera
2017-02-12, 18:22
  #11
Medlem
svettigafettsvinets avatar
Vad menar du med "samma djup"? Det beror helt och hållet på om databasanslutningen och timern är sykron eller asynkron. Gris-variabeln kan alltså bli odefinierad trots att det finns en return beroende på hur funktionen ser ut.
Citera
2017-02-12, 18:27
  #12
Medlem
Mia-Rovys avatar
Citat:
Ursprungligen postat av svettigafettsvinet
Vad menar du med "samma djup"? Det beror helt och hållet på om databasanslutningen och timern är sykron eller asynkron.
Se min edit för exempel på olika "djup". Två funktioner som gör samma sak, fast den ena är synkron och den andra asynkron.

Den ena fryser hela applikationen i 30 sekunder och returnerar sedan "Klar!", och den andra fortsätter att köra hela applikationen och anropar sedan callbacken efter 30 sekunder med värdet "Klar!".

Citat:
Ursprungligen postat av svettigafettsvinet
Gris-variabeln kan alltså bli odefinierad trots att det finns en return beroende på hur funktionen ser ut.
Nej. Finns det en return så kommer variabeln att få det värdet som returneras
__________________
Senast redigerad av Mia-Rovy 2017-02-12 kl. 18:31.
Citera
  • 1
  • 2

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback