In this lesson, we will learn how to fetch data from external APIs and integrate it with our GraphQL server. This skill is crucial when building real-world applications, as data often resides in different places. By combining GraphQL with external APIs, you can create a more robust and comprehensive data layer in your applications.
Previously, you learned how to handle GraphQL mutations, manage complex queries, and set up real-time subscriptions. This lesson will build on those skills, focusing on fetching external data.
A GraphQL schema defines the types and the structure of queries. Here’s the schema we’ll use in this lesson:
TypeScript1import { gql } from 'apollo-server'; 2 3const typeDefs = gql` 4 type Book { 5 id: ID! 6 title: String! 7 author: String! 8 } 9 10 type Query { 11 books: [Book] 12 externalBooks: [Book] 13 } 14`;
Here, we define a Book
type with fields id
, title
, and author
. We also define books
and externalBooks
queries to fetch books from local and external sources, respectively.
Resolvers define how to fetch data for each type in the schema. We've learned about resolvers in previous lessons, but here's a quick reminder of their purpose.
TypeScript1import fetch from 'node-fetch'; 2 3const resolvers = { 4 Query: { 5 books: () => [ 6 { id: '1', title: 'The Hobbit', author: 'J.R.R. Tolkien' }, 7 { id: '2', title: 'Harry Potter', author: 'J.K. Rowling' } 8 ], 9 externalBooks: async () => { 10 const response = await fetch('https://api.example.com/books'); 11 return response.json(); 12 } 13 } 14};
In the books
resolver, we return a static list of books. For externalBooks
, we use node-fetch
to get book data from an external API.
- The
books
resolver returns a hardcoded array of book objects. - The
externalBooks
resolver performs an asynchronous operation usingfetch
to get data from an external URL and then returns the JSON response.
Next, we will set up Apollo Server to use our schema and resolvers.
TypeScript1import { ApolloServer } from 'apollo-server'; 2 3const server = new ApolloServer({ typeDefs, resolvers }); 4 5server.listen().then(({ url }) => { 6 console.log(`🚀 Server ready at ${url}`); 7});
This code initializes Apollo Server with our defined schema and resolvers, and then starts the server. Once running, you should see:
Plain text1🚀 Server ready at http://localhost:4000/
To test our server and fetch both local and external book data, we will write a simple script using node-fetch
.
TypeScript1import fetch from 'node-fetch'; 2 3const query = ` 4 query { 5 books { 6 id 7 title 8 author 9 } 10 externalBooks { 11 id 12 title 13 author 14 } 15 } 16`; 17 18const url = 'http://localhost:4000/'; 19 20fetch(url, { 21 method: 'POST', 22 headers: { 23 'Content-Type': 'application/json', 24 }, 25 body: JSON.stringify({ 26 query, 27 }), 28}) 29 .then((response) => response.json()) 30 .then((data) => console.log(JSON.stringify(data, null, 2))) 31 .catch((error) => console.error('Error:', error));
- We define a GraphQL query to fetch
books
andexternalBooks
. - We use
fetch
to send this query to our running server. - The response is then logged to the console.
If everything is set up correctly, running this script should produce an output similar to:
JSON1{ 2 "data": { 3 "books": [ 4 { 5 "id": "1", 6 "title": "The Hobbit", 7 "author": "J.R.R. Tolkien" 8 }, 9 { 10 "id": "2", 11 "title": "Harry Potter", 12 "author": "J.K. Rowling" 13 } 14 ], 15 "externalBooks": [ 16 // Data fetched from the external API 17 ] 18 } 19}
In this lesson, you learned how to define a schema, create resolvers for both local and external data sources, set up Apollo Server, and query the server. Here are the key points:
- GraphQL schema and the role of resolvers.
- Fetching data from external APIs using
node-fetch
. - Integrating external APIs into your Apollo Server.
Next, you will apply these concepts in hands-on practice exercises. Experiment with querying different external APIs and consolidating your knowledge.
Congratulations on making it this far. You're now well-equipped to handle external data in your GraphQL applications. Keep practicing to master these skills!