Promises jsou nezbytnou součástí aplikací s asynchronním voláním služeb. Jak název napovídá, jde o slib. Volaná služba vrací příslib, že „něco“ vrátí, ať už je to cokoliv. Uvnitř Promise se poté provede asynchronní volání služby a jakmile je vrácen Response, zavolá se resolve(), popřípadě reject(). Pomocí Promises se lze vyvarovat nevhodnému používání Event Manageru. Střílení eventů a navěšování eventů je také cesta, kterou lze asynchronní volání obsluhovat. Podle mě je to zároveň cesta do pekel. Posudťe čitelnost sami:

let some_async = function() {
	return new Promise(function(resolve, reject) {
		resolve(); // Call after async done
	});
};

some_async()
.then((response) => {
	console.log('Async done!');
	console.log('response:', response);
})
.catch((error) => {
	console.log('Async error!');
	console.log('error:', error);
});

Tomu, kdo službu volal, je navrácena odpověď okamžitě ve formě příslibu. Pomocí nějakého Event Manageru by pak vzniklo něco takového:

eventmanager.attach('some_async', function(data, err){
	if (err){
		// CATCH BLOCK
		console.log('Async error!');

		return;
	}

	// THEN BLOCK
	console.log('Async done!');
});

// Call after async done
eventmanager.trigger('some_async', false);

Je jasné, že mít aplikaci prošpikovanou eventlistenery není úplně to pravé ořechové. K čemu se Promises používají je tedy naprosto jasné.

Nedávno jsme řešili problém s transakcemi. Potřebovali jsme docílit toho, aby se requesty na služby sbíraly do zásobníku a odeslaly se najednou v jendom requestu jako transakce. To má hned několik důvodů:

  • Z vlastností transakcí: ACID

    buď se to prostě provede celé, nebo se neprovede nic. O tom transakce ve své podstatě jsou, pokud se nehodláme bavit o úrovních izolace.

  • Spojení se serverem je nákladná operace

    je mnohem efektivnější sesbírat si více operací a poslat je v jednom requestu. Response vám přijde tak, jak si ho uděláte ;) ideálně jako sadu odpovědí na jednotlivé requesty v transakci.

    pozn.: nemusí to být rovnou transakce, může to být jen stack služeb = některá služba může selhat, ale ostatní se provedou

Nějak takto:

{
  "module": "Admin_Index",
  "section": "Rest",
  "action": "transaction",
  "data": {
	"parts": {
	  "services": [
		{
		  "module": "Ticket",
		  "section": "Ticket",
		  "action": "create",
		  "data": {
			"parts": {
			  "ticket": {
				"name": "Test complex ticket transactions",
				"type": "task",
				"id_ticket_project": 1,
				"id_ticket_priority": 1
			  }
			}
		  }
		},
		{
		  "module": "Ticket",
		  "section": "TicketSolver",
		  "action": "create",
		  "data": {
			"parts": {
			  "ticket_solver": {
				"id_ticket": "[0:data:id]",
				"id_ticket_person": 1,
				"id_ticket_status": 1
			  }
			}
		  }
		}
	  ]
	}
  }
}

Narazili jsme na to, že instance Promise je objektem, do kterého se nedá dostat zvenčí a má pouze privátní metody. Pokud tedy vytvořím Promise, pak s ní už nic neudělám. Vytáhli jsme si tedy privátní metodu resolve() a reject() ven už při tvorbě. A po provedení transakce jsme pak jednotlivé Promisy obsloužili.

let services = [];

function addJob(service){
	return new Promise(function(resolve, reject){
		services.push({
			service: service,
			resolve: resolve,
			reject : reject,
		})
	});
};

Tímto způsobem lze vytvořit komplexní chování uvnitř transakce. Vevnitř se požadavek může libovolně pokřivit. Odpověď tomu, kdo požadavek do transakce poslal, se vrátí aniž by vůbec tušil, že se něco křivilo.