Wrapping the creation of an Observable inside of a Function allows you delay the creation of the Observable until it is needed. This becomes really important when the Observable is created from a Promise due to the way Promises execute on creation.
Current Code:
<template> <section class="section"> <button class="button" v-stream:click="click$">Click</button> <h2> {{name$}} </h2> <img v-stream:error="imageError$" :src="image$" alt=""> </section> </template> <script> import { from, merge } from 'rxjs'; import { switchMap, pluck, map, mapTo } from 'rxjs/operators'; export default { name: 'app', domStreams: ['click$', 'imageError$'], subscriptions() { const person$ = from( this.$http.get( "https://starwars.egghead.training/people/1" ) ).pipe( pluck('data') ) const luke$ = this.click$.pipe( switchMap(() => person$) ) const name$ = luke$.pipe( pluck('name') ) const loadImage$ = luke$.pipe( pluck('image'), map(src => `https://starwars.egghead.trainin/${src}` ) ) const failImage$ = this.imageError$ .pipe( mapTo(`http://via.placeholder.com/400x400`) ) const image$ = merge( loadImage$, failImage$ ) return { name$, image$ } } }; </script>
The highlight part of code will be run once page loaded. So it means before the button was clicked, we already send a network request.
To defer the network request, we can do:
<template> <section class="section"> <button class="button" v-stream:click="click$">Click</button> <h2> {{name$}} </h2> <img v-stream:error="imageError$" :src="image$" alt=""> </section> </template> <script> import { from, merge } from 'rxjs'; import { switchMap, pluck, map, mapTo } from 'rxjs/operators'; export default { name: 'app', domStreams: ['click$', 'imageError$'], subscriptions() { const loadPerson = (url) => from( this.$http.get( url ) ).pipe( pluck('data') ) const luke$ = this.click$.pipe( mapTo("https://starwars.egghead.training/people/1"), switchMap((url) => loadPerson(url)) ); const name$ = luke$.pipe( pluck('name') ) const loadImage$ = luke$.pipe( pluck('image'), map(src => `https://starwars.egghead.training/${src}` ) ) const failImage$ = this.imageError$ .pipe( mapTo(`http://via.placeholder.com/400x400`) ) const image$ = merge( loadImage$, failImage$ ) return { name$, image$ } } }; </script>