Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Asynchronous JavaScript - there and back again

Asynchronous JavaScript - there and back again

Maciej Treder

June 10, 2020
Tweet

More Decks by Maciej Treder

Other Decks in Technology

Transcript

  1. function saySomethingNice():void { console.log(`Nice to meet you.`); } function greet(name:

    string): void { console.log(`Hello ${name}!`); saySomethingNice(); } greet(`John`); Hello John! Nice to meet you.
  2. function saySomethingNice():void { console.log(`Nice to meet you.`); } function greet(name:

    string): void { setTimeout(() => console.log(`Hello ${name}!`, 0)); saySomethingNice(); } greet(`John`); Nice to meet you. Hello John!
  3. Event Loop stack callbacks queue function saySthNice():void { } function

    greet(name: string): void { saySthNice(); } greet(`John`); setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  4. Event Loop stack callbacks queue main() function saySthNice():void { }

    function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  5. Event Loop greet() stack callbacks queue main() function saySthNice():void {

    } function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  6. Event Loop greet() stack callbacks queue main() function saySthNice():void {

    } function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  7. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  8. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  9. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout() console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  10. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout() console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  11. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  12. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); saySthNice() console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  13. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); saySthNice() console.log() console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`);
  14. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); saySthNice() console.log() console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you.
  15. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); saySthNice() console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you.
  16. Event Loop greet() stack setTimeout API callbacks queue main() function

    saySthNice():void { } function greet(name: string): void { saySthNice(); } greet(`John`); console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you.
  17. Event Loop stack setTimeout API callbacks queue main() function saySthNice():void

    { } function greet(name: string): void { saySthNice(); } greet(`John`); console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you.
  18. Event Loop stack setTimeout API callbacks queue function saySthNice():void {

    } function greet(name: string): void { saySthNice(); } greet(`John`); console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you.
  19. Event Loop stack setTimeout API callbacks queue function saySthNice():void {

    } function greet(name: string): void { saySthNice(); } greet(`John`); console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you.
  20. Event Loop stack setTimeout API callbacks queue function saySthNice():void {

    } function greet(name: string): void { saySthNice(); } greet(`John`); console.log() setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you. Hello John!
  21. Event Loop stack setTimeout API callbacks queue function saySthNice():void {

    } function greet(name: string): void { saySthNice(); } greet(`John`); setTimeout(() => console.log(`Hello ${name}!`, 0)); saySthNice(); console.log(`Nice to meet you.`); Nice to meet you. Hello John!
  22. Case study maciejtreder.github.io/asynchronous-javascript/ [ { "id": 1, "name": "James Cameron"

    }, { "id": 2, "name": "Quentin Tarantino" }, { "id": 3, "name": "Wes Anderson" }, { "id": 4, "name": "Stanley Kubrick" } ] [ { "id": 4, "title": "Django Unchained" }, { "id": 5, "title": "Inglourious Basterds" }, { "id": 6, "title": "Grindhouse" } ] { "id": 1, "reviewer": "Andy", "rating": 10 }, { "id": 2, "reviewer": "Margaret", "rating": 5 }, { "id": 3, "reviewer": "Bridget", "rating": 8 } ] /directors /directors/{id}/movies /movies/{id}/reviews
  23. const request = require('request'); request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`, {json: true}, (err, res,body)

    => { console.log(body); }); [ { id: 1, name: 'James Cameron' }, { id: 2, name: 'Quentin Tarantino' }, { id: 3, name: 'Wes Anderson' }, { id: 4, name: 'Stanley Kubrick' } ]
  24. const request = require('request'); }); }); }); }); request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`,

    {json: true}, (err, res, directors) => { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id;
  25. const request = require('request'); }); }); }); }); request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`,

    {json: true}, (err, res, directors) => { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`, {json: true}, (err, res, movies) => { let checkedMoviesCount = 0;
  26. const request = require('request'); }); }); }); }); request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`,

    {json: true}, (err, res, directors) => { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`, {json: true}, (err, res, movies) => { let checkedMoviesCount = 0; movies.forEach(movie => { request(`https://maciejtreder.github.io./asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, reviews) => {
  27. const request = require('request'); }); }); }); }); request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`,

    {json: true}, (err, res, directors) => { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`, {json: true}, (err, res, movies) => { let checkedMoviesCount = 0; movies.forEach(movie => { request(`https://maciejtreder.github.io./asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, reviews) => { checkedMoviesCount++; aggregatedScore = 0; reviews.forEach(review => aggregatedScore += review.rating); movie.averageRating = aggregatedScore / reviews.length;
  28. const request = require('request'); }); }); }); }); request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`,

    {json: true}, (err, res, directors) => { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`, {json: true}, (err, res, movies) => { let checkedMoviesCount = 0; movies.forEach(movie => { request(`https://maciejtreder.github.io./asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, reviews) => { checkedMoviesCount++; aggregatedScore = 0; reviews.forEach(review => aggregatedScore += review.rating); movie.averageRating = aggregatedScore / reviews.length; if (checkedMoviesCount === movies.length) { movies.sort((m1, m2) => m2.averageRating - m1.averageRating); console.log(`The best movie by Quentin Tarantino is... ${movies[0].title} !!!`); }
  29. const request = require('request'); }); }); }); }); request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`,

    {json: true}, (err, res, directors) => { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`, {json: true}, (err, res, movies) => { let checkedMoviesCount = 0; movies.forEach(movie => { request(`https://maciejtreder.github.io./asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, reviews) => { checkedMoviesCount++; aggregatedScore = 0; reviews.forEach(review => aggregatedScore += review.rating); movie.averageRating = aggregatedScore / reviews.length; if (checkedMoviesCount === movies.length) { movies.sort((m1, m2) => m2.averageRating - m1.averageRating); console.log(`The best movie by Quentin Tarantino is... ${movies[0].title} !!!`); }
  30. request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`, {json: true}, (err, res, body) => findDirector(body, 'Quentin

    Tarantino’)); function findDirector(directors, name) { let directorId = directors.find(director => director.name === name).id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${directorId}/ movies`, {json: true}, (err, res, body) => getReviews(body, name)); }
  31. request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`, {json: true}, (err, res, body) => findDirector(body, 'Quentin

    Tarantino’)); function findDirector(directors, name) { let directorId = directors.find(director => director.name === name).id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${directorId}/ movies`, {json: true}, (err, res, body) => getReviews(body, name)); } function getReviews(movies, director) { let checkedSoFar = {count: 0}; movies.forEach(movie => { request(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, body) => calculateAverageScore(body, movie, director, checkedSoFar, movies )); }); }
  32. const request = require('request'); function findDirector(directors, name) { let directorId

    = directors.find(director => director.name === name).id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${directorId}/ movies`, {json: true}, (err, res, body) => getReviews(body, name)); function getReviews(movies, director) { let checkedSoFar = {count: 0}; movies.forEach(movie => { request(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, body) => calculateAverageScore(body, movie, director, checkedSoFar, movies )); }); }
  33. const request = require('request'); function findDirector(directors, name) { let directorId

    = directors.find(director => director.name === name).id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${directorId}/ movies`, {json: true}, (err, res, body) => getReviews(body, name)); function getReviews(movies, director) { let checkedSoFar = {count: 0}; movies.forEach(movie => { request(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, body) => calculateAverageScore(body, movie, director, checkedSoFar, movies )); }); } function calculateAverageScore(reviews, movie, director, checkedSoFar, movies) { checkedSoFar.count++; aggregatedScore = 0; count = 0; reviews.forEach(review => { aggregatedScore += review.rating; count++; }); movie.averageRating = aggregatedScore / count; if (checkedSoFar.count == movies.length) { movies.sort((m1, m2) => m2.averageRating - m1.averageRating); console.log(`The best movie by ${director} is... ${movies[0].title} !!!`); } }
  34. const request = require('request'); function calculateAverageScore(reviews, movie, director, checkedSoFar, movies)

    { checkedSoFar.count++; aggregatedScore = 0; count = 0; reviews.forEach(review => { aggregatedScore += review.rating; count++; }); movie.averageRating = aggregatedScore / count; if (checkedSoFar.count == movies.length) { movies.sort((m1, m2) => m2.averageRating - m1.averageRating); console.log(`The best movie by ${director} is... ${movies[0].title} !!!`); } } function getReviews(movies, director) { let checkedSoFar = {count: 0}; movies.forEach(movie => { request(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, body) => calculateAverageScore(body, movie, director, checkedSoFar, movies)); }); } function findDirector(directors, name) { let directorId = directors.find(director => director.name === name).id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${directorId}/ movies`, {json: true}, (err, res, body) => getReviews(body, name)); } request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`, {json: true}, (err, res, body) => findDirector(body, 'Quentin Tarantino'));
  35. const request = require('request'); function calculateAverageScore(reviews, movie, director, checkedSoFar, movies)

    { checkedSoFar.count++; aggregatedScore = 0; count = 0; reviews.forEach(review => { aggregatedScore += review.rating; count++; }); movie.averageRating = aggregatedScore / count; if (checkedSoFar.count == movies.length) { movies.sort((m1, m2) => m2.averageRating - m1.averageRating); console.log(`The best movie by ${director} is... ${movies[0].title} !!!`); } } function getReviews(movies, director) { let checkedSoFar = {count: 0}; movies.forEach(movie => { request(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`, {json: true}, (err, res, body) => calculateAverageScore(body, movie, director, checkedSoFar, movies)); }); } function findDirector(directors, name) { let directorId = directors.find(director => director.name === name).id; request(`https://maciejtreder.github.io/asynchronous-javascript/directors/${directorId}/ movies`, {json: true}, (err, res, body) => getReviews(body, name)); } request(`https://maciejtreder.github.io/asynchronous-javascript/ directors`, {json: true}, (err, res, body) => findDirector(body, 'Quentin Tarantino'));
  36. Promises const promise1 = new Promise<string>(resolve => { setTimeout(() =>

    resolve(`Value from promise 1`), 1000); }); promise1.then(value => console.log(`Promise resolved with value: ${value}`)); promise1.then(value => console.log(`One more time ${value}`)); Promise resolved with value: Value from promise 1 One more time Value from promise 1
  37. Promises const promise1 = new Promise<string>(resolve => { resolve(`Value from

    promise 1`); resolve(`Promise resolves only once!`); }); promise1.then(value => console.log(`Promise resolved with value: ${value}`)); Promise resolved with value: Value from promise 1
  38. Promises const promise2 = new Promise<string>((resolve, reject) => { reject({reason:

    `Reject type doesn't depend on the Promise type, and it's always any.`}); }); promise2.then(value => {}, rejection => console.log(`Handled rejection`, rejection)); promise2.then(value => {}).catch(rejection => console.log(`Another way of handling rejection`, rejection)); Handled rejection { reason: 'Reject type doesn\'t depend on the Promise type, and it\'s always any.’} Another way of handling rejection { reason: 'Reject type doesn\'t depend on the Promise type, and it\'s always any.’}
  39. Promises const promise2 = new Promise<string>((resolve) => { throw {reason:

    `Reject type doesn't depend on the Promise type, and it's always any.`}; }); promise2.then(value => {}, rejection => console.log(`Handled rejection`, rejection)); promise2.then(value => {}).catch(rejection => console.log(`Another way of handling rejection`, rejection)); Handled rejection { reason: 'Reject type doesn\'t depend on the Promise type, and it\'s always any.’} Another way of handling rejection { reason: 'Reject type doesn\'t depend on the Promise type, and it\'s always any.’}
  40. This won’t work const promise2 = new Promise<string>((resolve, reject) =>

    { reject({reason: `Reject type doesn't depend on the Promise type, and it's always any.`}); }); promise2.then(value => {}); //unhandled rejection try { promise2.then(value => {}); } catch(error) { console.log(`Catched error`); } (node:14312) UnhandledPromiseRejectionWarning: #<Object>
  41. Chaining promise1 .then(val => square(val)) .then(value => console.log(value)); 9 const

    promise1 = Promise.resolve(3); const square = (val) => Promise.resolve(val * val); promise1.then(value => { square(value).then(value => { console.log(value); }); }); ==
  42. Chaining promise1 .then(val => square(val)) .then(() => {throw {};}) .then(val

    => console.log(val)) .catch(error => console.log(`Catched`)) .finally(() => console.log(`Finally statement`)); Catched Finally statement
  43. Chaining promise1 .then(val => square(val)) .then(() => {throw null;}) .catch(error

    => { console.log(`Error in second promise`) return 1; }) .then(val => console.log(val)) .catch(error => console.log(`Catched: ${error}`)) .finally(() => console.log(`Finally statement`)); Error in second promise 1 Finally statement
  44. Combining const promise1 = Promise.resolve(3); const square = (val) =>

    Promise.resolve(val * val); const promise2 = Promise.reject('Rejecting that!'); Promise.all([promise1, square(2)]).then(val => console.log(val)); Promise.all([promise1, square(2), promise2]) .then(val => console.log(val)) .catch(error => console.log(`Failed because of: ${error}`)); [ 3, 4 ] Failed because of: Rejecting that!
  45. Combining const promise1 = Promise.resolve(3); const square = (val) =>

    Promise.resolve(val * val); const promise2 = Promise.reject('Rejecting that!'); Promise.all([ promise1.catch(() => undefined), square(2).catch(() => undefined ), promise2.catch(() => undefined ) ]) .then(val => console.log(val)) .catch(error => console.log(`Failed because of: ${error}`)); [ 3, 4, undefined ]
  46. Combining const allSettled = require('promise.allsettled'); allSettled.shim(); const promise1 = Promise.resolve(3);

    const square = (val) => Promise.resolve(val * val); const promise2 = Promise.reject('Rejecting that!'); Promise.allSettled([promise1, square(2), promise2]) .then(val => console.log(val)) .catch(error => console.log(`Failed because of: ${error}`)); [ { status: 'fulfilled', value: 3 }, { status: 'fulfilled', value: 4 }, { status: 'rejected', reason: 'Rejecting that!' } ]
  47. Combining const promise1 = Promise.resolve(3); const square = (val) =>

    Promise.resolve(val * val); const promise2 = Promise.reject('Rejecting that!'); Promise.race([promise1, square(2), promise2]) .then(val => console.log(val)) .catch(error => console.log(`Failed because of: ${error}`)); 3
  48. Combining function watchDog() { return new Promise((resolve, reject) => setTimeout(()

    => reject(), 2000)); } const promise1 = Promise.resolve(3); const square = (val) => Promise.resolve(val * val); const promise2 = Promise.reject('Rejecting that!'); Promise.race([ promise2.catch(() => new Promise()), square(2), promise1, watchDog() ]) .then(val => console.log(val)) .catch(_ => console.log(`Non of the promises resolves before watchdog`)); 3
  49. const fetch = require('node-fetch'); fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/`) .then(response => response.json()) .then(directors =>

    { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; return fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`); }) .then(response => response.json()) Quentin Movies
  50. const fetch = require('node-fetch'); fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/`) .then(response => response.json()) .then(directors =>

    { let tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; return fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`); }) .then(response => response.json()) .then(movies => { let reviewsArr = []; movies.forEach(movie => { reviewsArr.push( fetch(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`) .then(response => response.json()).then(reviews => { return {movie: movie, reviews: reviews}; }) ); }); return Promise.all(reviewsArr); }) [{title: movie, reviews: []}]
  51. return fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`); }) .then(response => response.json()) .then(movies => {

    let reviewsArr = []; movies.forEach(movie => { reviewsArr.push( fetch(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`) .then(response => response.json()).then(reviews => { return {movie: movie, reviews: reviews}; }) ); }); return Promise.all(reviewsArr); }) [{title: movie, reviews: []}]
  52. return fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/${tarantinoId}/ movies`); }) .then(response => response.json()) .then(movies => {

    let reviewsArr = []; movies.forEach(movie => { reviewsArr.push( fetch(`https://maciejtreder.github.io/asynchronous-javascript/movies/${movie.id}/ reviews`) .then(response => response.json()).then(reviews => { return {movie: movie, reviews: reviews}; }) ); }); return Promise.all(reviewsArr); }) .then(reviewSets => { let moviesAndRatings = []; reviewSets.forEach(reviews => { let aggregatedScore = 0; reviews.reviews.forEach( review => aggregatedScore += review.rating ); let averageScore = aggregatedScore / reviews.reviews.length; moviesAndRatings.push({title: reviews.movie, averageScore: averageScore}); }); return moviesAndRatings.sort((m1, m2) => m2.averageScore - m1.averageScore)[0].title; }) .then(movie => console.log(` ${movie.title} !`)) [{title: movie, averageScore: score}]
  53. fetch(`/directors/`) /directors /directors/2/movies .then(directors => { let tarantinoId = directors.findTarantino();

    return fetch(`/directors/${tarantinoId}/movies`); }) /movies/{id}/reviews .then(movies => { let reviewsArr = fetchAllReviews(movies); return Promise.all(reviewsArr); }) .then(reviewSets => { let moviesAndRatings = calculateAverageScores(reviewSets); return moviesAndRatings.sort((m1, m2) => m2.aver ageScore - m1.averageScore)[0].title; }) .then(movie => console.log(`The best movie by Quen tin Tarantino is... ${movie.title}!`));
  54. import { Observable, Observer } from 'rxjs'; const clock$: Observable<string>

    = Observable.create((observer: Observer<string>) => { console.log('In Observable'); setInterval(() => { observer.next('tick'); }, 1000); }); RxJS clock$.subscribe(val => console.log(val)); In Observable; tick; tick; tick; tick; …
  55. RxJS const clock$: Subject<string> = new Subject<string>(); const interval =

    setInterval(() => { clock$.next('tick'); }, 1000); tick; tick let subscription = clock$.subscribe(val => console.log(val)); setTimeout(() => subscription.unsubscribe(), 3 * 1000);
  56. RxJS const clock$: Subject<string> = new Subject<string>(); const interval =

    setInterval(() => { clock$.next('tick'); }, 1000); tick; tick setTimeout(() => clock$.complete(), 8 * 1000); setTimeout(() => clearInterval(interval), 9 * 1000); let subscription = clock$.subscribe(val => console.log(val)); setTimeout(() => subscription.unsubscribe(), 3 * 1000); setTimeout(() => subscription = clock$.subscribe(val => console.log(val)), 4*1000); tick; tick; tick; tick
  57. Manipulating data const clock$: Subject<string> = new Subject<string>(); const interval

    = setInterval(() => { clock$.next('tick'); }, 1000); setTimeout(() => clock$.complete(), 8 * 1000) setTimeout(() => clearInterval(interval), 9 * 1000); tick; tock; tick; tock; tick; tock; tick; tock clock$.pipe( map((val, index) => index % 2 == 0 ? val : 'tock') ).subscribe(val => console.log(val)); import { map } from 'rxjs/operators';
  58. Error catching import { , Subject } from 'rxjs'; import

    { map, } from ‘rxjs/operators'; const clock$: Subject<string> = new Subject<string>(); const interval = setInterval(() => { clock$.next('tick'); }, 1000); setTimeout(() => clock$.complete(), 8 * 1000); setTimeout(() => clearInterval(interval), 9 * 1000); clock$.pipe( map((val, index) => index % 2 == 0 ? val : ‘tock’), ).subscribe(val => console.log(val)); tick; tock; tick; tock; setTimeout(() => console.log('Still alive?'), 12 * 1000);
  59. Error catching import { , Subject } from 'rxjs'; import

    { map, } from ‘rxjs/operators'; const clock$: Subject<string> = new Subject<string>(); const interval = setInterval(() => { clock$.next('tick'); }, 1000); setTimeout(() => clock$.complete(), 8 * 1000); setTimeout(() => clearInterval(interval), 9 * 1000); clock$.pipe( map((val, index) => index % 2 == 0 ? val : ‘tock’), ).subscribe(val => console.log(val)); tick; tock; tick; tock; Error: BOOOM! setTimeout(() => clock$.error(new Error('BOOOM!')), 5 * 1000); setTimeout(() => console.log('Still alive?'), 12 * 1000);
  60. Error catching import { , Subject } from 'rxjs'; import

    { map, } from ‘rxjs/operators'; const clock$: Subject<string> = new Subject<string>(); const interval = setInterval(() => { clock$.next('tick'); }, 1000); setTimeout(() => clock$.complete(), 8 * 1000); setTimeout(() => clearInterval(interval), 9 * 1000); clock$.pipe( map((val, index) => index % 2 == 0 ? val : ‘tock’), ).subscribe(val => console.log(val)); tick; tock; tick; tock; setTimeout(() => clock$.error(new Error('BOOOM!')), 5 * 1000); setTimeout(() => console.log('Still alive?'), 12 * 1000); catchError(error => of('Explosion!')) catchError of Explosion! Still alive?
  61. Error catching import { , Subject } from 'rxjs'; import

    { map, } from ‘rxjs/operators'; const clock$: Subject<string> = new Subject<string>(); const interval = setInterval(() => { clock$.next('tick'); }, 1000); setTimeout(() => clock$.complete(), 8 * 1000); setTimeout(() => clearInterval(interval), 9 * 1000); clock$.pipe( map((val, index) => index % 2 == 0 ? val : ‘tock’), ).subscribe(val => console.log(val)); tick; tock; tick; tock; setTimeout(() => clock$.error(new Error('BOOOM!')), 5 * 1000); setTimeout(() => console.log('Still alive?'), 12 * 1000); catchError(error => of('Explosion!')) catchError of Explosion! Still alive?
  62. RxJS 12 6 3 9 1 2 4 5 7

    8 10 11 tick tick tick tick tick tick tick tick tick tick tick tock tick tock tick tock tick tock BOOM! Explosion! Still alive? import { of, Subject } from 'rxjs'; import { map, catchError } from ‘rxjs/operators'; const clock$: Subject<string> = new Subject<string>(); const interval = setInterval(() => { clock$.next('tick'); }, 1000); setTimeout(() => clock$.error(new Error('BOOOM!')), 5 * 1000) setTimeout(() => clearInterval(interval), 6 * 1000); clock$.pipe( map((val, index) => index % 2 == 0 ? val : 'tock'), catchError(error => of('Explosion!')) ).subscribe(val => console.log(val)); setTimeout(() => console.log('Still alive?'), 12 * 1000);
  63. RxJS & REST const Axios = require('axios-observable').Axios; const map =

    require('rxjs/operators').map; const flatMap = require('rxjs/operators').flatMap; const combineLatest = require('rxjs').combineLatest; Axios.get('https://maciejtreder.github.io/asynchronous-javascript/directors/') .pipe( map(response => response.data), List of directors
  64. RxJS & REST const Axios = require('axios-observable').Axios; const map =

    require('rxjs/operators').map; const flatMap = require('rxjs/operators').flatMap; const combineLatest = require('rxjs').combineLatest; Axios.get('https://maciejtreder.github.io/asynchronous-javascript/directors/') .pipe( map(response => response.data), map(response => response.find(director => director.name == 'Quentin Tarantino').id), flatMap(id => Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/directors/ ${id}/movies`)), map(response => response.data), Quentin Movies
  65. RxJS & REST const Axios = require('axios-observable').Axios; const map =

    require('rxjs/operators').map; const flatMap = require('rxjs/operators').flatMap; const combineLatest = require('rxjs').combineLatest; Axios.get('https://maciejtreder.github.io/asynchronous-javascript/directors/') .pipe( map(response => response.data), map(response => response.find(director => director.name == 'Quentin Tarantino').id), flatMap(id => Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/directors/ ${id}/movies`)), map(response => response.data), flatMap(movies => { const observables$ = []; movies.forEach(movie => { Quentin Movies
  66. RxJS & REST map(response => response.data), map(response => response.find(director =>

    director.name == 'Quentin Tarantino').id), flatMap(id => Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/directors/ ${id}/movies`)), map(response => response.data), flatMap(movies => { const observables$ = []; movies.forEach(movie => { Quentin Movies
  67. RxJS & REST map(response => response.data), map(response => response.find(director =>

    director.name == 'Quentin Tarantino').id), flatMap(id => Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/directors/ ${id}/movies`)), map(response => response.data), flatMap(movies => { const observables$ = []; movies.forEach(movie => { observables$.push( Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/movies/$ {movie.id}/reviews`) .pipe( map(response => response.data), map(reviews => { let count = 0; let sum = 0; reviews.forEach(review => {count++; sum+=review.score}); return sum/reviews.length; }), map(average => { return {title: movie.title, averageScore: average}; }) ) ); }); Quentin Movies
  68. RxJS & REST map(response => response.data), map(response => response.find(director =>

    director.name == 'Quentin Tarantino').id), flatMap(id => Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/directors/ ${id}/movies`)), map(response => response.data), flatMap(movies => { const observables$ = []; movies.forEach(movie => { observables$.push( Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/movies/$ {movie.id}/reviews`) .pipe( map(response => response.data), map(reviews => { let count = 0; let sum = 0; reviews.forEach(review => {count++; sum+=review.score}); return sum/reviews.length; }), map(average => { return {title: movie.title, averageScore: average}; }) ) ); }); return combineLatest(observables$); }), map(movies => movies.sort((movie1, movie2) => movie2.averageScore - movie1.averageScore)), map(movies => movies[0].title) ) [{title: movie, averageScore: score}]
  69. RxJS & REST map(response => response.data), map(response => response.find(director =>

    director.name == 'Quentin Tarantino').id), flatMap(id => Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/directors/ ${id}/movies`)), map(response => response.data), flatMap(movies => { const observables$ = []; movies.forEach(movie => { observables$.push( Axios.get(`https://maciejtreder.github.io/asynchronous-javascript/movies/$ {movie.id}/reviews`) .pipe( map(response => response.data), map(reviews => { let count = 0; let sum = 0; reviews.forEach(review => {count++; sum+=review.score}); return sum/reviews.length; }), map(average => { return {title: movie.title, averageScore: average}; }) ) ); }); return combineLatest(observables$); }), map(movies => movies.sort((movie1, movie2) => movie2.averageScore - movie1.averageScore)), map(movies => movies[0].title) ) .subscribe(console.log); [{title: movie, averageScore: score}]
  70. RxJS pros const Axios = require('axios-observable').Axios; const map = require('rxjs/operators').map;

    const retry = require('rxjs/operators').retry; Axios.get('https://maciejtreder.github.io/asynchronous-javascript/directors/123') .pipe( map(resp => resp.data) ) .subscribe(console.log); retry(3),
  71. RxJS pros const Axios = require('axios-observable').Axios; const map = require('rxjs/operators').map;

    const retry = require('rxjs/operators').retry; Axios.get('https://maciejtreder.github.io/asynchronous-javascript/directors/123') .pipe( map(resp => resp.data) ) .subscribe(console.log); retry(3),
  72. Tracking the ISS with Real-Time Event Notifications Using Node.js, RxJS

    Observables, and Twilio Programmable SMS https://www.twilio.com/blog/real-time-event-notifications-using-node-js-rxjs-observables-twilio-programmable-sms
  73. Make the code synchronous again const getMultiplier = Promise.resolve(2); const

    multiply = (multiply, multiplier) => Promise.resolve(multiply * multiplier); let multiplier = getMultiplier; let result = multiply(10, multiplier); console.log(`Multiply result: ${result}`); getMultiplier .then(value => multiply(10, value)) .then(result => console.log(`Multiply result: ${result}`)); await await var multiplier = await getMultiplier; ^^^^^ SyntaxError: await is only valid in async function at new Script (vm.js:79:7) at createScript (vm.js:251:10) at Object.runInThisContext (vm.js:303:10) at Module._compile (internal/modules/cjs/loader.js:657:28) at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10) at Module.load (internal/modules/cjs/loader.js:599:32) at tryModuleLoad (internal/modules/cjs/loader.js:538:12) at Function.Module._load (internal/modules/cjs/loader.js:530:3) at Function.Module.runMain (internal/modules/cjs/loader.js:742:12) at startup (internal/bootstrap/node.js:283:19)
  74. Make the code asynchronous again! const multiplier = getMultiplier; const

    result = multiply(10, multiplier); console.log(`Multiply result: ${result}`); await await (async () => { })(); async function myFunction() { return "someValue"; } == function myFunction() { return Promise.resolve("someValue"); } Multiply result: 20 const getMultiplier = Promise.resolve(2); const multiply = (multiply, multiplier) => Promise.resolve(multiply * multiplier);
  75. vs let multiplier = getMultiplier; let result = multiply(10, multiplier);

    console.log(`Multiply result: ${result}`); await await (async () => { })(); getMultiplier .then(value => multiply(10, value)) .then(result => console.log(`Multiply result: ${result}`));
  76. async-await and RxJS import { Subject } from 'rxjs'; const

    clock$: Subject<number> = new Subject<number>(); let i = 0; const interval = setInterval(() => { clock$.next(i++); }, 1000); setTimeout(() => clock$.complete(), 4*1000); setTimeout(() => clearInterval(interval), 5 * 1000); (async () => { console.log(await clock$.toPromise()); })(); 2
  77. async-await error catching const promise = Promise.reject('rejection reason'); (async ()

    => { try { console.log(await promise); } catch (err) { console.log(`Error catched: ${err}`); } finally { console.log('Finally executes'); } })(); Error catched: rejection reason Finally executes
  78. const fetch = require('node-fetch'); (async () => { })(); const

    directors = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/`) .then(response => response.json()); const tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id;
  79. const fetch = require('node-fetch'); (async () => { })(); const

    directors = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/`) .then(response => response.json()); const tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; const quentinMovies = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/ directors/${tarantinoId}/movies`) .then(response => response.json());
  80. const fetch = require('node-fetch'); (async () => { })(); const

    directors = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/`) .then(response => response.json()); const tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; const quentinMovies = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/ directors/${tarantinoId}/movies`) .then(response => response.json()); const reviewsCall = []; quentinMovies.forEach(movie => { reviewsCall.push(fetch(`https://maciejtreder.github.io/asynchronous-javascript/movies/$ {movie.id}/reviews`) .then(resp => resp.json()) .then(resp => { return {title: movie.title, reviews: resp}; })); }); const reviews = await Promise.all(reviewsCall);
  81. const fetch = require('node-fetch'); (async () => { })(); const

    directors = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/`) .then(response => response.json()); const tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; const quentinMovies = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/ directors/${tarantinoId}/movies`) .then(response => response.json()); const reviewsCall = []; quentinMovies.forEach(movie => { reviewsCall.push(fetch(`https://maciejtreder.github.io/asynchronous-javascript/movies/$ {movie.id}/reviews`) .then(resp => resp.json()) .then(resp => { return {title: movie.title, reviews: resp}; })); }); const reviews = await Promise.all(reviewsCall); reviews.forEach(entry => { let aggregatedScore = 0; entry.reviews.forEach(review => aggregatedScore += review.rating); entry.score = aggregatedScore / entry.reviews.length; }); const best = reviews.sort((movie1, movie2) => movie2.score - movie1.score)[0].title; console.log(`The best movie by Quentin Tarantino is ${best}`);
  82. const fetch = require('node-fetch'); (async () => { })(); const

    directors = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/directors/`) .then(response => response.json()); const tarantinoId = directors.find(director => director.name === "Quentin Tarantino").id; const quentinMovies = await fetch(`https://maciejtreder.github.io/asynchronous-javascript/ directors/${tarantinoId}/movies`) .then(response => response.json()); const reviewsCall = []; quentinMovies.forEach(movie => { reviewsCall.push(fetch(`https://maciejtreder.github.io/asynchronous-javascript/movies/$ {movie.id}/reviews`) .then(resp => resp.json()) .then(resp => { return {title: movie.title, reviews: resp}; })); }); const reviews = await Promise.all(reviewsCall); reviews.forEach(entry => { let aggregatedScore = 0; entry.reviews.forEach(review => aggregatedScore += review.rating); entry.score = aggregatedScore / entry.reviews.length; }); const best = reviews.sort((movie1, movie2) => movie2.score - movie1.score)[0].title; console.log(`The best movie by Quentin Tarantino is ${best}`);
  83. Performance pitfall function promiseFunction1() { return new Promise(resolve => {

    setTimeout(() => { resolve("abc"); }, 2000); }); } function promiseFunction2() { return new Promise(resolve => { setTimeout(() => { resolve("abc"); }, 2000); }); } (async () => { console.log(await promiseFunction1()); console.log(await promiseFunction2()); })(); (async () => { const promisefn1 = promiseFunction1(); const promisefn2 = promiseFunction2(); console.log(await promisefn1); console.log(await promisefn2); })(); 2 sec 4 sec
  84. Callbacks RxJS Promises async-await asynchronous synchronous? asynchronous asynchronous repeatable one-shot

    repeatable (not) reusable reusable reusable (not) manipulatable manipulatable manipulatable REST WebSocket Dependent operations DOM events