Многообещающий JavaScript – Promises

Многообещающий JavaScript – Promises

rdner

Денис Речкунов
Ведущий JavaScript-разработчик

Немного издалека...

За что я люблю JavaScript?

А зачем нам вообще асинхронный код?

Callback

			callACat(function () {
				console.log('Hello, Cat!');
			});
		

Callback Hell

			callACat(function () {
				callADog(function () {
					callAHorse(function () {
						callSanta(function () {
							console.log('Where am I?');
						});
					});
				});
			});
		

Event Emitter

			phone
			 .on('cat', function(){ phone.callADog(); })
			 .on('dog', function(){ phone.callAHorse(); })
			 .on('horse', function(){ phone.callSanta(); })
			 .on('santa', function(){ console.log('Santa?'); });
			phone.callACat();
		

Promises

			phone.callACat()
			 .then(phone.callADog)
			 .then(phone.callAHorse)
			 .then(phone.callSanta)
			 .then(function(){ console.log('Santa?'); });
		

Promises

Откуда они взялись?

Реализации

Откуда они взялись в JavaScript?

Важные факты

Терминология

Что нам даёт Promise

Вместо этого...

			callACat(function () {
				callADog(function () {
					callAHorse(function () {
						callSanta(function () {
							console.log('Where am I?');
						});
					});
				});
			});
		

Вот это!

			phone.callACat()
			 .then(phone.callADog)
			 .then(phone.callAHorse)
			 .then(phone.callSanta)
			 .then(function(){ console.log('Santa?'); });
		

Больше примеров

Callback -> Promise

			new Promise(function (fulfill, reject) {
				phone.callACat(function (error, result) {
					if (error) {
						reject(error);
						return;
					}
					fulfill(result);
				});
			});
		

Thenable, Value -> Promise

			Promise.resolve(jQueryPromise);
			Promise.resolve(number);
			Promise.resolve(string);
			
			Promise.reject(new Error('Cat not found'));
		

Chaining

			phone.callACat()
			 .then(function (catResult) {
			   console.log(catResult);
			   return phone.callADog(); // Promise
			 })
			 .then(function (dogResult) {
			   console.log(dogResult);
			   return 'Hello, Dog!'; // Value
			 })
			 .then(function (msg) { console.log(msg); }); // Hello, Dog! 
		

Обработка ошибок

			phone.callACat()
			 .then(function () {
			   throw new Error('No cat!');
			 })
			 .then(function () {
			   console.log('This is a cat!'); // skipped
			 })
			 .catch(function (reason) {
			 	console.error(reason); // No cat!
			 });
		

Обработка ошибок

			phone.callACat()
			 .then(function () {
			   throw new Error('No cat!');
			 })
			 .then(function () {
			 		console.log('This is a cat!'); // skipped
			 	}, function (reason) {
			 		console.error(reason); // No cat!
			 	}); // for old browsers no .catch
		

Rethrow Error

			phone.callACat('Tom')
			 .then(function () {
			   throw new Error('No cat!')
			 })
			 .catch(function (reason) {
			 	reason.message += 'Tom';
			 	throw reason;
			 });
		

Promise.all()

			Promise.all([
			 phone.callACat(),
			 phone.callADog(),
			 phone.callAHorse()
			])
			 .then(function (resultsList) {
			 	console.log('Everybody are online!');
			 });
		

Promise.race()

			Promise.race([
			 phone.callACat(),
			 phone.callADog(),
			 phone.callAHorse()
			])
			 .then(function (value) {
			 	console.log('Who is speaking?');
			 });
		

Поддержка браузерами

Полезные ссылки

Спасибо за внимание!

Денис Речкунов, Flamp (denis@rdner.de)
rdner