


What do you want?
Use latest libraries!
So let's upgrade!
But... there are issues...
Who'll fix them
Not me
Not me
Let's wait...
Upgrade with confidence
@ktrz__ | /ktrz
05.12.2018, FrontendCon

Chris Trześniewski
Senior Frontend Developer @Scalac
https://slides.com/ktrz/fc2018
What's the story?
What's the story
Project using Angular
GraphQL API
Apollo Client (angular-apollo)
What's the motivation?
What's the motivation
Easier to customize
Clearer API
Query batching
Integration with NgRx
Ok, so let's just upgrade - right?
Let's upgrade
Clear upgrade path
API changed a bit
...
Let's upgrade
...
It seems ready... npm start
this.apollo.watchQuery({
query: foo,
variables: { a: a$, b: b$, c: c$ },
})
.subscribe((bar) => {
console.log(bar);
});this.apollo.watchQuery({
query: foo,
variables: { a: a$, b: b$, c: c$ },
})
.valueChanges
.subscribe((bar) => {
console.log(bar);
});
Title Text

Keep calm!

Long story short
Long story short
❌ no Observable variables
Long story short
this.apollo.watchQuery({
query: foo,
variables: { a: a$, b: b$, c: c$ },
})
.valueChanges
.subscribe((bar) => {
console.log(bar);
});Long story short



First solution
First solution
const variables$ = combineVariables({ a: a$, b: a$, c: c$ });
// {a: Observable, b: Observable, c: Observable} => Observable<{a,b,c}>
variables$.pipe(
switchMap(variables => {
return this.apollo.watchQuery({
query: foo,
variables: variables,
}).valueChanges;
}
)
)
.subscribe((bar) => {
console.log(bar);
});It works!
New watchQuery everytime
Second solution
const variables$ = combineVariables({a: a$, b: a$, c: c$});
// {a: Observable, b: Observable, c: Observable} => Observable<{a,b,c}>
const queryRef = this.apollo.watchQuery({
query: foo,
fetchResults: false,
});
variables$.pipe(
tap(variables => queryRef.setVariables(variables)),
switchMap(() => queryRef.valueChanges)
)
.subscribe((bar) => {
console.log(bar);
});Only one watchQuery
Let's back up a little
Let's back up a little
this.apollo.watchQuery({
query: foo,
variables: { a: a$, b: a$, c: c$ },
})
.subscribe((bar) => {
console.log(bar);
});const variables$ = combineVariables({a: a$, b: a$, c: c$});
// {a: Observable, b: Observable, c: Observable} => Observable<{a,b,c}>
const queryRef = this.apollo.watchQuery({
query: foo,
variables: variables,
fetchResults: false,
});
variables$.pipe(
tap(variables => queryRef.setVariables(variables)),
switchMap(() => queryRef.valueChanges)
)
.subscribe((bar) => {
console.log(bar);
});The ultimate goal
The ultimate goal
this.apollo.watchQuery({
query: foo,
variables: { a: a$, b: a$, c: c$ },
})
.subscribe((bar) => {
console.log(bar);
});Middleware to the rescue!
The ultimate goal
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
return {
link: from([
handleObservableVariables(),
httpLink.create({ uri })
]),
cache: new InMemoryCache(),
};
}Using middleware
The ultimate goal
export const handleObservableVariables = (ngZone: NgZone) =>
new RxjsLink({ onOperation: requestHandler(ngZone) });
return operation$.pipe(
switchMap(operation => {
const context = operation.getContext();const requestHandler = (zone: NgZone): OnOperation =>
(operation$: Observable<Operation>): Observable<Operation> => zone.runOutsideAngular(() => { if (checkVariables(context.variables$) {
return combineVariables(context.variables$).pipe(
switchMap(variables =>
of(prepareOperation(operation, variables)))
);
}
return of(operation);
}),
);
});Ultimate goal?
well... almost
The ultimate goal
this.apollo.watchQuery({
query: foo,
context: {
variables$: { a: a$, b: a$, c: c$ },
},
fetchResults: false,
})
.subscribe((bar) => {
console.log(bar);
});this.apollo.watchQuery({
query: foo,
variables: { a: a$, b: a$, c: c$ },
})
.subscribe((bar) => {
console.log(bar);
});Still... it's nice already :)
Thank you!
Upgrade with confidence
By Chris Trześniewski
Upgrade with confidence
- 863