Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Gentle Introduction to GraphQL Resolvers

Steve Kinney
January 28, 2020
140

A Gentle Introduction to GraphQL Resolvers

Steve Kinney

January 28, 2020
Tweet

Transcript

  1. @stevekinney What even is a resolver? • Short answer: It’s

    a function or method that resolves a value for a type or field in your schema. • Every field on every type is backed by a function called a resolver.
  2. @stevekinney Resolving values and objects • If the return value

    of a function is a literal (e.g. a string or a number or a boolean). Cool, we’re done here. • Otherwise, if it’s an object, we’re going to dip down into that object and try to resolve it as well. • We’ll keep diving deeper until we’ve gotten to the bottom of things.
  3. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox const resolvers = { Query: {

    artists() { return [...artists]; }, albums() { return new Promise(resolve => resolve([...albums])); }, songs() { return axios.get(‘/some-endpoint') .then(response => response.data); } } };
  4. @stevekinney If a resolver returns a promise, we’re obviously going

    to have to—umm— resolve wait for it before diving down.
  5. @stevekinney We should probably use GraphQL for this problem, right?

    • A user might want to pull up all of the artists in their library with their albums. • They might just want to see a list of albums. • Or, maybe, they just want to a big ol’ list of songs. • (We’re going to ignore playlists for now.)
  6. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox type Query { artists: [Artist!] albums:

    [Album!] songs: [Song!] artist(id: Int!): Artist! album(id: Int!): Album! song(id: Int!): Song! } type Mutation { addArtist(name: String!): Artist addAlbum(title: String!, year: Int, artistId: Int): Album addSong(title: String!, time: Int, artistId: Int, albumId: Int): Song }
  7. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox [ { "id": 1, "name": "The

    National" }, { "id": 2, "name": "Camp Cope" }, { "id": 3, "name": "Rilo Kiley" } ]
  8. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox [ { "id": 1, "artistId": 1,

    "title": "Trouble Will Find Me", "year": 2013 }, { "id": 2, "artistId": 2, "title": "How to Socialize and Make Friends", "year": 2018 } ]
  9. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox [ { "title": "Done", "time": "4:47",

    "artistId": 2, "albumId": 5, "id": 1 }, { "title": "Flesh & Electricity", "time": "3:57", "artistId": 2, "albumId": 5, "id": 2 }, { "title": "West Side Story", "time": "5:32", "artistId": 2, "albumId": 5, "id": 3 }, ]
  10. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox const resolvers = { Query: {

    artists(root, args, context, info) { return [{ id: 1, name: 'The National' }]; } } };
  11. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox const resolvers = { Query: {

    // … artist(root, args) { return artists.find(artist => artist.id === args.id); } // … } };
  12. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox Query: { // … Artist: {

    albums(artist) { // artist is the parent value return albums.filter(album => album.artistId === artist.id); }, songs(artist) { return songs.filter(song => song.artistId === artist.id); } }, // … } };
  13. @stevekinney By default, resolvers will look to see if whatever

    you’re looking for is a property on the object.
  14. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox const resolvers = { Artist: {

    // You don't need to do this. name(artist) { return artist.name; }, albums(artist) { return albums.filter(album => album.artistId === artist.id); }, songs(artist) { return songs.filter(song => song.artistId === artist.id); } } };
  15. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox const resolvers = { Mutation: {

    addArtist(_, args) { const artist = { ...args, id: generateId() }; artists.push(artist); return artist; } } };
  16. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox const resolvers = { Mutation: {

    addArtist(_, args) { return axios.post('/artists', args) .then(response => response.data); } } };
  17. @stevekinney What is context? • Short answer: It’s an object

    shared by all of the resolvers. • It's mutable. • It's destroyed between every request.
  18. @stevekinney What might you store in context? • Authentication data

    • The request object in something like Express • API fetching functions • Database connections
  19. Play: https://graph-jukebox.glitch.me/ Edit: https://glitch.com/edit/#!/graph-jukebox const server = new ApolloServer({ typeDefs,

    resolvers, context: ({ req }) => ({ authScope: getScope(req.headers.authorization) }) }); // Resolver (root, args, context) => { if (context.authScope !== ADMIN) { throw AuthenticationError('not admin'); } // More stuff… };
  20. @stevekinney Let’s poke around the working version of the application,

    shall we? • https://glitch.com/edit/#!/graph-jukebox • Let’s look at how to add additional properties. • Let’s look at an example that makes AJAX requests.