Promises
	Promises
	Návrhový vzor pro CPS
	Ondřej Žára, Seznam.cz
	 
	 
	Bojový plán
	
		- Problémy asynchronních funkcí
- Promise: zobecněný callback
- Pokročilé partie
 
	Problémy asynchronních funkcí
	Problémy asynchronních funkcí
	
var output = computeStuff(input);
var output = requestStuff(input, callback);
	
		- Výsledek práce funkce není znám ve chvíli jejího ukončení
- Návratová hodnota je zpravidla bezvýznamná
- Předáním callbacku ztrácíme kontext (pokud nepoužijeme bind)
- Co když "zpožděná" část funkce vyhodí výjimku?
Problémy asynchronních funkcí
	
		- Jak zřetězit (serializovat) více asynchronních volání?
- Co když je funkce asynchronní podmíněně?
- Co když asynchronní funkci zavolám opakovaně?
- Kdo určuje signaturu callbacku?
- Jak v kódu nahradit synchronní volání voláním asynchronním?
 
	Promise: zobecněný callback
	Starý dobrý callback
	
		- Předávat callback (+ volitelně kontext) je tradiční řešení
- Události, setTimeout, XHR, …
- Zpravidla stačí, ale je neobratný
Promise: zobecněný callback
	
		- Promises jsou návrhový vzor
- Asynchronní funkce nepřijímá callback, namísto toho vrací "budoucí hodnotu" (promise)
- Promise popisuje hodnotu, která ještě nebyla nalezena (ale časem bude)
- Když mám Promise, můžu ji poprosit o vykonání callbacku
Promise: základní použití
	
var requestData = function() {
	var promise = new JAK.Promise();
	
	/* var xhr = ... */
	
	xhr.addEventListener("ready", function(data) { 
		promise.fulfill(data); 
	});
	
	/* xhr.send() */
	
	return promise;
}
	Promise: základní použití
	
var promise = requestData();
promise.then(callback);
promise.then(jinyCallback);
	Promise: opáčko
	
		- new JAK.Promise()je obecná neznámá hodnota
- promise.fulfill(data)posune promise do stavu "splněno" (max. jednou)
- promise.then(cb)je zavěšení posluchače
- Posluchačů lze zavěsit více
- Posluchač bude vykonán vždy s jedním parametrem (tím, co dostane fulfill)
Promise: návratová hodnota then
	
		- Metoda thenvrací další Promise
- Tím se celá věc nečekaně komplikuje :-)
- Nová promise, vrácená then, bude fulfillnuta hodnotou vrácenou callbackem
- Pokud callback vrátí Promise (třetí), ta druhá bude fulfillnuta až po jejím splnění
Promise: návratová hodnota then
	
var promise = requestData1();
promise.then(requestData2).then(requestData3).then(...);
/* requestData{1..3} vrací promise. 
   Kdyby náhodou třeba requestData2 vrátila rovnou výsledek,
     nic by se nerozbilo (ale requestData3 by bylo voláno ihned).
*/
	 
	Pokročilé partie
	Pokročilé partie: pořadí volání
	
		- Promise je možno splnit (fulfill) ještě před volánímthen
- Tato varianta odpovídá synchronnímu volání (výsledek známe v době skončení funkce)
- Callback předaný do thenbude ovšem volán asynchronně (setTimeout(0))
- To proto, že volající nemusí vědět, kdy bude hodnota známa
Pokročilé partie: reject
	
		- Promise má ještě metodu reject(reason)
- Změna stavu promise na "selhalo"
- Metoda thenmá volitelný druhý callback pro případ selhání
- Alternativa pro asynchronní propagaci chyb
Pokročilé partie: reject
	
var request = function() {
	var promise = new JAK.Promise();
	xhr.onreadystatechange = function() {
		if (xhr.status == 200) { promise.fulfill(); } else { promise.reject(); }
	}
	return promise;
}
var promise = request();
promise.then(zpracujData, vypisChybu);
	Pokročilé partie: when
	
		- Statická metoda whendostane pole promisů a vrátí novou
- Tato bude fullfillnuta pole fullfillment values, jakmile dojde ke splnění celého pole
- Pokud jedna z pole rejectne, tato whenbude rejectnuta
 
	Rekapitulace
	Rekapitulace
	
		- Promises jsou volitelnou alternativou k předávání callbacků
- Promises musí "někdo" vracet a "někdo jiný" zpracovávat
- Promise si sama řeší libovolný počet "posluchačů", async. fci to nezajímá
- Volání .then()lze řetězit
- Callback v thenje vždy volán s parametrem, který vrátilo předchozí volání
- Pokud callback vrátí Promise, pokračování volání dalších thenje navázáno na jejífulfill/reject
- I synchronní funkce může vrátit Promise