#7 "Многообещающий JavaScript – Promises" Денис Речкунов

30
pragmadash Денис Речкунов Ведущий JavaScript-разработчик Многообещающий JavaScript – Promises

Transcript of #7 "Многообещающий JavaScript – Promises" Денис Речкунов

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

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

www.princexml.com
Prince - Non-commercial License
This document was created with Prince, a great way of getting web content onto paper.

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

За что я люблю JavaScript?• Очень удобно писать асинхронный код...

• JavaScript-код всегда исполняется в одном потоке

• Все "блокирующие" операции выполняются асинхронно

(в node.js это libuv)

• Благодаря Event Loop, не нужна синхронизация между потоками

(блокировки, каналы, вот это всё)

3

А зачем нам вообще асинхронный код?• Для параллельной обработки большого набора данных

• Чтобы процесс не простаивал, пока исполняется длительная операция

• К сожалению, для первого JavaScript совсем не годится

• Зато всё круто со вторым...

4

CallbackcallACat(function () {

console.log('Hello, Cat!');

});

01.

02.

03.

6

Callback HellcallACat(function () {

callADog(function () {

callAHorse(function () {

callSanta(function () {

console.log('Where am I?');

});

});

});

});

01.

02.

03.

04.

05.

06.

07.

08.

09.

7

Event Emitterphone

.on('cat', function(){ phone.callADog(); })

.on('dog', function(){ phone.callAHorse(); })

.on('horse', function(){ phone.callSanta(); })

.on('santa', function(){ console.log('Santa?'); });

phone.callACat();

01.

02.

03.

04.

05.

06.

8

Promisesphone.callACat()

.then(phone.callADog)

.then(phone.callAHorse)

.then(phone.callSanta)

.then(function(){ console.log('Santa?'); });

01.

02.

03.

04.

05.

9

Promises

Откуда они взялись?• "Promise" 1976 год – Daniel P. Friedman и David Wise

"Функция, возвращающая будущее значение"

• "Future" 1977 год – Henry Baker и Carl Hewitt

"Представление будущего значения"

Статья Википедии

11

Реализации• C++11 (std::future and std::promise)

• C# (System.Concurrent.Task, async/await)

• Java (java.util.concurrent.Future)

• Python (concurrent.futures)

• JavaScript (ECMAScript 6/2015)

12

Откуда они взялись в JavaScript?• Февраль 2010 Kris Kowal (Разработчик Q) предложил Promises/A

• 12 июня 2012 Brian Cavalier, Domenic Denicola и компания

предложили Promises/A+

• Спецификация Promises/A+, стала частью ECMAScript 6/2015

13

Важные факты• jQuery Promise не соответствует спецификации

• Каждый Promise начинает исполнение на след. итерации Event Loop

• Каждый последующий .then() или .catch() тоже на след. итерации

14

Терминология• Thenable – объект с методом .then (например jQuery Promise)

• Pending Promise – обещание ожидает значения

• Fulfilled Promise – выполненное обещание

• Rejected Promise – отвергнутое обещание

• Reason – описание, почему обещание отвергнуто

(обычно объект Error)

15

Что нам даётPromise

Вместо этого...callACat(function () {

callADog(function () {

callAHorse(function () {

callSanta(function () {

console.log('Where am I?');

});

});

});

});

01.

02.

03.

04.

05.

06.

07.

08.

09.

17

Вот это!phone.callACat()

.then(phone.callADog)

.then(phone.callAHorse)

.then(phone.callSanta)

.then(function(){ console.log('Santa?'); });

01.

02.

03.

04.

05.

18

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

Callback -> Promisenew Promise(function (fulfill, reject) {

phone.callACat(function (error, result) {

if (error) {

reject(error);

return;

}

fulfill(result);

});

});

01.

02.

03.

04.

05.

06.

07.

08.

09.

20

Thenable, Value -> PromisePromise.resolve(jQueryPromise);

Promise.resolve(number);

Promise.resolve(string);

Promise.reject(new Error('Cat not found'));

01.

02.

03.

04.05.

21

Chainingphone.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!

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.

22

Обработка ошибок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!

}) ;

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.

23

Обработка ошибок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

01.

02.

03.

04.

05.

06.

07.

08.

09.

24

Rethrow Errorphone.callACat('Tom')

.then(function () {

throw new Error('No cat!')

})

.catch(function (reason) {

reason.message += 'Tom';

throw reason;

});

01.

02.

03.

04.

05.

06.

07.

08.

25

Promise.all()Promise.all([

phone.callACat(),

phone.callADog(),

phone.callAHorse()

])

.then(function (resultsList) {

console.log('Everybody are online!');

});

01.

02.

03.

04.

05.

06.

07.

08.

26

Promise.race()Promise.race([

phone.callACat(),

phone.callADog(),

phone.callAHorse()

])

.then(function (value) {

console.log('Who is speaking?');

});

01.

02.

03.

04.

05.

06.

07.

08.

27

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

Полезные ссылки• Спецификация Promises/A+

• Mozilla Developer Network – Promise

• Коротко и понятно о Promises

• Чистый полифил Promise для старых браузеров

29

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

Денис Речкунов, Flamp ([email protected])

pragmadash