Connect.Tech 2017: Dive into RxJS Observables

Connect.Tech 2017: Dive into RxJS Observables

94bd558238b69c45d3d3e15797ae94f7?s=128

Jeremy Fairbank

September 22, 2017
Tweet

Transcript

  1. 3.
  2. 5.
  3. 7.

    function fetchCustomerNameForOrder(orderId, done, fail) { fetchOrder(orderId, function(err, order) { if

    (err) { logError(err); fail(err); } else { fetchCustomer( order.customerId, function(err, customer) { if (err) { logError(err); fail(err); } else { done(customer.name); } } ); } }); }
  4. 8.

    function fetchCustomerNameForOrder(orderId, done, fail) { fetchOrder(orderId, function(err, order) { if

    (err) { logError(err); fail(err); } else { fetchCustomer( order.customerId, function(err, customer) { if (err) { logError(err); fail(err); } else { done(customer.name); } } ); } }); }
  5. 9.

    function fetchCustomerNameForOrder(orderId, done, fail) { fetchOrder(orderId, function(err, order) { if

    (err) { logError(err); fail(err); } else { fetchCustomer( order.customerId, function(err, customer) { if (err) { logError(err); fail(err); } else { done(customer.name); } } ); } }); }
  6. 16.

    • More readable and maintainable async code • Better error

    handling • More declarative and versatile syntax • Capable of handling events, streams, and HTTP
  7. 20.
  8. 22.

    const { Observable } = require('rxjs'); const source = Observable.of(1,

    2, 3); source.subscribe(x => console.log(x)); // 1 // 2 // 3
  9. 23.

    const { Observable } = require('rxjs'); const source = Observable.of(1,

    2, 3); source.subscribe(x => console.log(x)); // 1 // 2 // 3
  10. 24.

    const { Observable } = require('rxjs'); const source = Observable.of(1,

    2, 3); source.subscribe(x => console.log(x)); // 1 // 2 // 3
  11. 25.

    const { Observable } = require('rxjs'); const source = Observable.of(1,

    2, 3); source.subscribe(x => console.log(x)); // 1 // 2 // 3
  12. 36.
  13. 37.
  14. 54.

    Observable.range(1, 100) .map(n => n * 2) .filter(n => n

    > 4) .take(2) .subscribe(x => console.log(x)); // 6 // 8
  15. 55.

    Observable.range(1, 100) .map(n => n * 2) .filter(n => n

    > 4) .take(2) .subscribe(x => console.log(x)); // 6 // 8
  16. 56.

    Observable.range(1, 100) .map(n => n * 2) .filter(n => n

    > 4) .take(2) .subscribe(x => console.log(x)); // 6 // 8
  17. 57.

    Observable.range(1, 100) .map(n => n * 2) .filter(n => n

    > 4) .take(2) .subscribe(x => console.log(x)); // 6 // 8
  18. 58.

    Observable.range(1, 100) .map(n => n * 2) .filter(n => n

    > 4) .take(2) .subscribe(x => console.log(x)); // 6 // 8
  19. 60.

    console.log n * 2 map subscribe n > 4 1

    Observable.range(1, 100) filter 2 take
  20. 61.

    console.log n * 2 map subscribe n > 4 1

    Observable.range(1, 100) filter 2 take
  21. 62.

    console.log n * 2 map subscribe n > 4 2

    Observable.range(1, 100) filter 2 take
  22. 63.

    console.log n * 2 map subscribe n > 4 2

    Observable.range(1, 100) filter 2 take
  23. 64.

    console.log n * 2 map subscribe n > 4 2

    Observable.range(1, 100) filter 2 take ×
  24. 66.

    console.log n * 2 map subscribe n > 4 2

    Observable.range(1, 100) filter 2 take
  25. 67.

    console.log n * 2 map subscribe n > 4 2

    Observable.range(1, 100) filter 2 take
  26. 68.

    console.log n * 2 map subscribe n > 4 4

    Observable.range(1, 100) filter 2 take
  27. 72.

    console.log n * 2 map subscribe n > 4 3

    Observable.range(1, 100) filter 2 take
  28. 73.

    console.log n * 2 map subscribe n > 4 3

    Observable.range(1, 100) filter 2 take
  29. 74.

    console.log n * 2 map subscribe n > 4 6

    Observable.range(1, 100) filter 2 take
  30. 76.

    ✓ console.log n * 2 map subscribe n > 4

    Observable.range(1, 100) filter 2 take 6
  31. 80.

    console.log n * 2 map subscribe n > 4 4

    Observable.range(1, 100) filter 1 take
  32. 81.

    console.log n * 2 map subscribe n > 4 4

    Observable.range(1, 100) filter 1 take
  33. 82.

    console.log n * 2 map subscribe n > 4 8

    Observable.range(1, 100) filter 1 take
  34. 84.

    ✓ console.log n * 2 map subscribe n > 4

    Observable.range(1, 100) filter 1 take 8
  35. 88.

    let counter = 0; function updateCounter(n) { counter += n;

    counterEl.innerHTML = counter; } incrementBtn.addEventListener('click', () => { updateCounter(1); }); decrementBtn.addEventListener('click', () => { updateCounter(-1); });
  36. 89.

    let counter = 0; function updateCounter(n) { counter += n;

    counterEl.innerHTML = counter; } incrementBtn.addEventListener('click', () => { updateCounter(1); }); decrementBtn.addEventListener('click', () => { updateCounter(-1); });
  37. 90.

    Observable.fromEvent(incrementBtn, 'click') .mapTo(1) .scan((acc, curr) => acc + curr, 0)

    .subscribe((counter) => { counterEl.innerHTML = counter; });
  38. 91.

    Observable.fromEvent(incrementBtn, 'click') .mapTo(1) .scan((acc, curr) => acc + curr, 0)

    .subscribe((counter) => { counterEl.innerHTML = counter; });
  39. 92.

    Observable.fromEvent(incrementBtn, 'click') .mapTo(1) .scan((acc, curr) => acc + curr, 0)

    .subscribe((counter) => { counterEl.innerHTML = counter; });
  40. 93.

    Observable.fromEvent(incrementBtn, 'click') .mapTo(1) .scan((acc, curr) => acc + curr, 0)

    .subscribe((counter) => { counterEl.innerHTML = counter; });
  41. 94.

    Observable.fromEvent(incrementBtn, 'click') .mapTo(1) .scan((acc, curr) => acc + curr, 0)

    .subscribe((counter) => { counterEl.innerHTML = counter; });
  42. 95.

    Observable.fromEvent(incrementBtn, 'click') .mapTo(1) .scan((acc, curr) => acc + curr, 0)

    .subscribe((counter) => { counterEl.innerHTML = counter; });
  43. 96.

    Observable.fromEvent(incrementBtn, 'click') .mapTo(1) .scan((acc, curr) => acc + curr, 0)

    .subscribe((counter) => { counterEl.innerHTML = counter; });
  44. 106.

    1 mapTo subscribe scan 1 acc + curr 1 Counter

    value counterEl.innerHTML = counter
  45. 113.

    1 mapTo subscribe scan 2 acc + curr 2 Counter

    value counterEl.innerHTML = counter
  46. 115.
  47. 116.
  48. 117.
  49. 118.
  50. 119.
  51. 120.

    acc + curr 1 mapTo subscribe 0 scan -1 mapTo

    Increment Decrement counterEl.innerHTML = counter
  52. 121.

    acc + curr 1 mapTo subscribe 0 scan -1 mapTo

    Increment Decrement e counterEl.innerHTML = counter
  53. 122.

    acc + curr 1 mapTo subscribe 0 scan -1 mapTo

    Increment Decrement e counterEl.innerHTML = counter
  54. 123.

    acc + curr 1 mapTo subscribe 0 scan -1 mapTo

    Increment Decrement 1 counterEl.innerHTML = counter
  55. 124.

    acc + curr 1 mapTo subscribe 0 scan -1 mapTo

    Increment Decrement 1 counterEl.innerHTML = counter
  56. 125.

    acc + curr 1 mapTo subscribe 1 scan -1 mapTo

    Increment Decrement 1 counterEl.innerHTML = counter
  57. 126.

    acc + curr 1 mapTo subscribe 1 scan -1 mapTo

    Increment Decrement 1 counterEl.innerHTML = counter
  58. 127.

    acc + curr 1 mapTo subscribe 1 scan -1 mapTo

    Increment Decrement counterEl.innerHTML = counter
  59. 128.

    acc + curr 1 mapTo subscribe 1 scan -1 mapTo

    Increment Decrement e counterEl.innerHTML = counter
  60. 129.

    acc + curr 1 mapTo subscribe 1 scan -1 mapTo

    Increment Decrement e counterEl.innerHTML = counter
  61. 130.

    acc + curr 1 mapTo subscribe 1 scan -1 mapTo

    Increment Decrement -1 counterEl.innerHTML = counter
  62. 131.

    acc + curr 1 mapTo subscribe 1 scan -1 mapTo

    Increment Decrement -1 counterEl.innerHTML = counter
  63. 132.

    acc + curr 1 mapTo subscribe 0 scan -1 mapTo

    Increment Decrement 0 counterEl.innerHTML = counter
  64. 133.

    acc + curr 1 mapTo subscribe 0 scan -1 mapTo

    Increment Decrement 0 counterEl.innerHTML = counter
  65. 134.
  66. 139.

    Promise fetchOrders() .then(orders => orders.filter( order => order.customerName === 'Tucker'

    )) .then(orders => orders.map(order => order.id)) .then((orderIds) => { orderIds.forEach(id => console.log(id)); });
  67. 140.

    Promise fetchOrders() .then(orders => orders.filter( order => order.customerName === 'Tucker'

    )) .then(orders => orders.map(order => order.id)) .then((orderIds) => { orderIds.forEach(id => console.log(id)); });
  68. 141.

    Promise fetchOrders() .then(orders => orders.filter( order => order.customerName === 'Tucker'

    )) .then(orders => orders.map(order => order.id)) .then((orderIds) => { orderIds.forEach(id => console.log(id)); });
  69. 142.

    Promise fetchOrders() .then(orders => orders.filter( order => order.customerName === 'Tucker'

    )) .then(orders => orders.map(order => order.id)) .then((orderIds) => { orderIds.forEach(id => console.log(id)); });
  70. 143.

    fetchOrders() .mergeAll() .filter( order => order.customerName === 'Tucker' ) .map(order

    => order.id) .subscribe(id => console.log(id)); Observable
  71. 144.

    fetchOrders() .mergeAll() .filter( order => order.customerName === 'Tucker' ) .map(order

    => order.id) .subscribe(id => console.log(id)); Observable
  72. 145.

    fetchOrders() .mergeAll() .filter( order => order.customerName === 'Tucker' ) .map(order

    => order.id) .subscribe(id => console.log(id)); Observable
  73. 146.

    fetchOrders() .mergeAll() .filter( order => order.customerName === 'Tucker' ) .map(order

    => order.id) .subscribe(id => console.log(id)); Observable
  74. 147.

    fetchOrders() .mergeAll() .filter( order => order.customerName === 'Tucker' ) .map(order

    => order.id) .subscribe(id => console.log(id)); Observable
  75. 149.

    const promise = fetchOrders() .then((orders) => { orders.forEach((order) => {

    console.log(order); }); }); promise.cancel(); Promise
  76. 150.

    const promise = fetchOrders() .then((orders) => { orders.forEach((order) => {

    console.log(order); }); }); promise.cancel(); Promise
  77. 151.

    const promise = fetchOrders() .then((orders) => { orders.forEach((order) => {

    console.log(order); }); }); promise.cancel(); Promise ×
  78. 152.

    const subscription = fetchOrders() .subscribe((orders) => { orders.forEach((order) => {

    console.log(order); }); }); subscription.unsubscribe(); Observable
  79. 153.

    const subscription = fetchOrders() .subscribe((orders) => { orders.forEach((order) => {

    console.log(order); }); }); subscription.unsubscribe(); Observable Cancel request
  80. 156.
  81. 157.

    Observables const o1 = fetchOrders(); const o2 = fetchOrders(); const

    o3 = fetchOrders(); o1.subscribe(); o2.subscribe(); o3.subscribe();
  82. 158.

    Observables Lazy const o1 = fetchOrders(); const o2 = fetchOrders();

    const o3 = fetchOrders(); o1.subscribe(); o2.subscribe(); o3.subscribe();
  83. 159.

    Observables Lazy const o1 = fetchOrders(); const o2 = fetchOrders();

    const o3 = fetchOrders(); o1.subscribe(); o2.subscribe(); o3.subscribe(); Issue Request
  84. 166.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Custom Observable Creation
  85. 167.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Custom Observable Creation
  86. 168.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Custom Observable Creation
  87. 169.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Custom Observable Creation
  88. 170.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Custom Observable Creation
  89. 171.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Custom Observable Creation
  90. 172.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Custom Observable Creation ?
  91. 176.

    Observable.of(1, 2, 3) .subscribe({ next: x => console.log(x), complete: ()

    => console.log('Done!'), }); // 1 // 2 // 3 // Done!
  92. 177.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } fetchOrders().mergeAll().subscribe({ next: x => console.log(x), complete: () => console.log('Done!'), });
  93. 178.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } fetchOrders().mergeAll().subscribe({ next: x => console.log(x), complete: () => console.log('Done!'), });
  94. 179.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } fetchOrders().mergeAll().subscribe({ next: x => console.log(x), complete: () => console.log('Done!'), });
  95. 181.

    const source = Observable.create((subscriber) => { subscriber.next(1); subscriber.error(new Error('Uh oh'));

    subscriber.next(2); }); source.subscribe({ next: x => console.log(x), complete: () => console.log('Done!'), error: e => console.error(e), }); // 1 // Error: Uh oh
  96. 182.

    const source = Observable.create((subscriber) => { subscriber.next(1); subscriber.error(new Error('Uh oh'));

    subscriber.next(2); }); source.subscribe({ next: x => console.log(x), complete: () => console.log('Done!'), error: e => console.error(e), }); // 1 // Error: Uh oh
  97. 183.

    const source = Observable.create((subscriber) => { subscriber.next(1); subscriber.error(new Error('Uh oh'));

    subscriber.next(2); }); source.subscribe({ next: x => console.log(x), complete: () => console.log('Done!'), error: e => console.error(e), }); // 1 // Error: Uh oh
  98. 184.

    const source = Observable.create((subscriber) => { subscriber.next(1); subscriber.error(new Error('Uh oh'));

    subscriber.next(2); }); source.subscribe({ next: x => console.log(x), complete: () => console.log('Done!'), error: e => console.error(e), }); // 1 // Error: Uh oh Never called
  99. 185.

    const source = Observable.create((subscriber) => { subscriber.next(1); subscriber.error(new Error('Uh oh'));

    subscriber.next(2); }); source.subscribe(x => console.log(x)); No error handler, so what happens?
  100. 187.

    const source = Observable.create((subscriber) => { subscriber.next(1); subscriber.error(new Error('Uh oh'));

    subscriber.next(2); }); source.subscribe(x => console.log(x)); No swallowed errors!
  101. 188.

    fetchOrders() .catch((e) => { logError(e); return legacyFetchOrders() .catch((e2) => {

    logError(e2); return Observable.of([]); }) }) .subscribe(x => console.log(x)); Catching
  102. 189.

    fetchOrders() .catch((e) => { logError(e); return legacyFetchOrders() .catch((e2) => {

    logError(e2); return Observable.of([]); }) }) .subscribe(x => console.log(x)); Catching
  103. 190.

    fetchOrders() .catch((e) => { logError(e); return legacyFetchOrders() .catch((e2) => {

    logError(e2); return Observable.of([]); }) }) .subscribe(x => console.log(x)); Catching
  104. 211.

    function fetchOrders() { return Observable.create((subscriber) => { fetchOrdersFromDb((orders) => {

    subscriber.next(orders); subscriber.complete(); }); }); } Resource requested/created at subscription time
  105. 212.
  106. 213.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); }); }
  107. 214.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); }); }
  108. 215.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); }); }
  109. 216.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); }); }
  110. 223.
  111. 234.

    const url = 'ws://example.com/orders'; const socket = new WebSocket(url); function

    ordersStream() { return Observable.create((subscriber) => { socket.addEventListener('message', (data) => { subscriber.next(data); }); }); }
  112. 235.

    const url = 'ws://example.com/orders'; const socket = new WebSocket(url); function

    ordersStream() { return Observable.create((subscriber) => { socket.addEventListener('message', (data) => { subscriber.next(data); }); }); } Resource created outside subscription
  113. 236.

    const url = 'ws://example.com/orders'; const socket = new WebSocket(url); function

    ordersStream() { return Observable.create((subscriber) => { socket.addEventListener('message', (data) => { subscriber.next(data); }); }); } Close over existing resource when subscribing
  114. 237.
  115. 238.

    Shared stream of data const stream = ordersStream(); const sub1

    = stream.subscribe(x => console.log(x)); const sub2 = stream.subscribe(x => console.log(x));
  116. 248.

    subscriber .next(event.data) ... WebSocket Subscribed Observable console.log ... New Subscribed

    Observable console.log stream.subscribe(...) stream.subscribe(...)
  117. 249.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); }) .share(); } Share It
  118. 250.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); }) .share(); } Share It
  119. 251.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); }) .share(); } Share It
  120. 252.
  121. 253.

    Shared stream of data too const stream = ordersStream(); const

    sub1 = stream.subscribe(x => console.log(x)); const sub2 = stream.subscribe(x => console.log(x));
  122. 254.
  123. 255.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); return () => { socket.close(); }; }) .share(); }
  124. 256.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); return () => { socket.close(); }; }) .share(); } Called when all subscriptions unsubscribe
  125. 257.

    function ordersStream() { return Observable.create((subscriber) => { const url =

    'ws://example.com/orders'; const socket = new WebSocket(url); socket.addEventListener('message', (data) => { subscriber.next(data); }); return () => { socket.close(); }; }) .share(); } Close socket, deallocate resources, etc.
  126. 258.
  127. 259.

    fetchOrders() .mergeAll() .filter( order => order.customerName === 'Tucker' ) .map(order

    => order.id) .subscribe(id => console.log(id)); ? Recall
  128. 275.
  129. 276.

    Observable.of(1, 2, 3) .map(n => n * 2) .subscribe(x =>

    console.log(x)); // 2 // 4 // 6 Delay?
  130. 277.

    Observable.of(1, 2, 3) .map(n => Observable.of(n * 2)) .subscribe(x =>

    console.log(x)); // ScalarObservable { value: 2 } // ScalarObservable { value: 4 } // ScalarObservable { value: 6 }
  131. 278.

    Observable.of(1, 2, 3) .map(n => Observable.of(n * 2)) .subscribe(x =>

    console.log(x)); // ScalarObservable { value: 2 } // ScalarObservable { value: 4 } // ScalarObservable { value: 6 }
  132. 279.

    Observable.of(1, 2, 3) .map(n => Observable.of(n * 2)) .subscribe(x =>

    console.log(x)); // ScalarObservable { value: 2 } // ScalarObservable { value: 4 } // ScalarObservable { value: 6 }
  133. 293.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ))

    .subscribe(x => console.log(x)); // <tick> // 2 // 4 // 6
  134. 294.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ))

    .subscribe(x => console.log(x)); // <tick> // 2 // 4 // 6
  135. 295.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ))

    .subscribe(x => console.log(x)); // <tick> // 2 // 4 // 6
  136. 296.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ))

    .subscribe(x => console.log(x)); // <tick> // 2 // 4 // 6 ?
  137. 312.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ),

    1) .subscribe(x => console.log(x)); // <tick> // 2 // <tick> // 4 // <tick> // 6
  138. 313.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ),

    1) .subscribe(x => console.log(x)); // <tick> // 2 // <tick> // 4 // <tick> // 6
  139. 314.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ),

    1) .subscribe(x => console.log(x)); // <tick> // 2 // <tick> // 4 // <tick> // 6
  140. 315.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ),

    1) .subscribe(x => console.log(x)); // <tick> // 2 // <tick> // 4 // <tick> // 6
  141. 316.

    Observable.of(1, 2, 3) .mergeMap(n => ( Observable.of(n * 2).delay(1000) ),

    1) .subscribe(x => console.log(x)); // <tick> // 2 // <tick> // 4 // <tick> // 6
  142. 317.

    Observable.of(1, 2, 3) .concatMap(n => ( Observable.of(n * 2).delay(1000) ))

    .subscribe(x => console.log(x)); // <tick> // 2 // <tick> // 4 // <tick> // 6
  143. 335.

    Observable.of(1, 2, 3) .concatMap((id) => { const url = `/orders/${id}`;

    return Observable.ajax.get(url) .delay(1000); }) .pluck('response') .bufferCount(3) .subscribe(x => console.log(x)); // [ { id: '1', name: 'Order 1' }, // { id: '2', name: 'Order 2' }, // { id: '3', name: 'Order 3' } ]
  144. 336.

    Observable.of(1, 2, 3) .concatMap((id) => { const url = `/orders/${id}`;

    return Observable.ajax.get(url) .delay(1000); }) .pluck('response') .bufferCount(3) .subscribe(x => console.log(x)); // [ { id: '1', name: 'Order 1' }, // { id: '2', name: 'Order 2' }, // { id: '3', name: 'Order 3' } ]
  145. 337.

    Observable.of(1, 2, 3) .concatMap((id) => { const url = `/orders/${id}`;

    return Observable.ajax.get(url) .delay(1000); }) .pluck('response') .bufferCount(3) .subscribe(x => console.log(x)); // [ { id: '1', name: 'Order 1' }, // { id: '2', name: 'Order 2' }, // { id: '3', name: 'Order 3' } ]
  146. 338.

    Observable.of(1, 2, 3) .concatMap((id) => { const url = `/orders/${id}`;

    return Observable.ajax.get(url) .delay(1000); }) .pluck('response') .bufferCount(3) .subscribe(x => console.log(x)); // [ { id: '1', name: 'Order 1' }, // { id: '2', name: 'Order 2' }, // { id: '3', name: 'Order 3' } ]
  147. 353.

    const promise = Promise.all([ fetchOrder(1), fetchOrder(2), fetchOrder(3), ]); promise.then(x =>

    console.log(x)); // [ { id: '1', name: 'Order 1' }, // { id: '2', name: 'Order 2' }, // { id: '3', name: 'Order 3' } ]
  148. 354.

    const promise = Promise.all([ fetchOrder(1), fetchOrder(2), fetchOrder(3), ]); promise.then(x =>

    console.log(x)); // [ { id: '1', name: 'Order 1' }, // { id: '2', name: 'Order 2' }, // { id: '3', name: 'Order 3' } ]
  149. 355.

    const source = Observable.forkJoin( fetchOrder(1), fetchOrder(2), fetchOrder(3) ); source.subscribe(x =>

    console.log(x)); // [ { response: { id: 1, name: 'Order 1' } }, // { response: { id: 2, name: 'Order 2' } }, // { response: { id: 3, name: 'Order 3' } } ]
  150. 356.

    const source = Observable.forkJoin( fetchOrder(1), fetchOrder(2), fetchOrder(3) ); source.subscribe(x =>

    console.log(x)); // [ { response: { id: 1, name: 'Order 1' } }, // { response: { id: 2, name: 'Order 2' } }, // { response: { id: 3, name: 'Order 3' } } ]
  151. 357.

    const source = Observable.forkJoin( fetchOrder(1), fetchOrder(2), fetchOrder(3) ); source.subscribe(x =>

    console.log(x)); // [ { response: { id: 1, name: 'Order 1' } }, // { response: { id: 2, name: 'Order 2' } }, // { response: { id: 3, name: 'Order 3' } } ] Observable or Promise
  152. 367.

    • Declarative, lazy operations • Expressive event management • No

    more error swallowing • Rate limiting and concurrent processing
  153. 368.

    • Declarative, lazy operations • Expressive event management • No

    more error swallowing • Rate limiting and concurrent processing ✓ ✓ ✓ ✓