Apollo-server: [apollo-datasource-rest] (node:30845) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'fetch' of undefined

Created on 11 Mar 2020  路  3Comments  路  Source: apollographql/apollo-server

This bug report should include:

  • [ ] A short, but descriptive title. The title doesn't need "Apollo" in it.
  • [ ] The package name and version of Apollo showing the problem.
  • [ ] If applicable, the last version of Apollo where the problem did _not_ occur.
  • [ ] The expected behavior.
  • [ ] The actual behavior.
  • [ ] A simple, runnable reproduction!
    Please make a GitHub repository that anyone can clone and run and see the
    problem. Other great ways to demonstrate a reproduction are using our
    CodeSandbox template (https://codesandbox.io/s/apollo-server), or re-mixing
    our Glitch template (https://glitch.com/~apollo-launchpad).
    -->

First off, you DO NOT explain how one can obtain info you demand above.
Hence I only add info I know how to obtain.

server/package.json

  "dependencies": {
    "apollo-datasource": "^0.1.3",
    "apollo-datasource-rest": "^0.1.5",
    "apollo-server": "2.6.1",
    "apollo-server-testing": "2.6.1",
    "graphql": "^14.2.1",
    "isemail": "^3.1.3",
    "nodemon": "^1.18.4",
    "sequelize": "^4.39.0",
    "sqlite3": "^4.0.3"
  },

apollo-datasource-rest throws error in GET requersts

The expected behavior.
const {RESTDataSource} = require('apollo-datasource-rest'); can make REST request without errors.

The actual behavior.

(node:30845) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'fetch' of undefined
    at LaunchAPI.<anonymous> (/Users/admin//apollo/fullstack-tutorial/start/server/node_modules/apollo-datasource-rest/dist/RESTDataSource.js:148:63)
    at Generator.next (<anonymous>)
    at /Users/admin//apollo/fullstack-tutorial/start/server/node_modules/apollo-datasource-rest/dist/RESTDataSource.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/admin//apollo/fullstack-tutorial/start/server/node_modules/apollo-datasource-rest/dist/RESTDataSource.js:3:12)
    at trace (/Users/admin//apollo/fullstack-tutorial/start/server/node_modules/apollo-datasource-rest/dist/RESTDataSource.js:143:78)
    at LaunchAPI.<anonymous> (/Users/admin//apollo/fullstack-tutorial/start/server/node_modules/apollo-datasource-rest/dist/RESTDataSource.js:186:24)
    at Generator.next (<anonymous>)
    at /Users/admin//apollo/fullstack-tutorial/start/server/node_modules/apollo-datasource-rest/dist/RESTDataSource.js:7:71
    at new Promise (<anonymous>)
(node:30845) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:30845) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

A simple, runnable reproduction!

  1. Follow your Tutorial
  2. Follow this step Hook up your data sources up to Connect a database section (don't implement it)
  3. Open index.js file and add the following lines:
const api = new LaunchAPI();
const launches = api.getAllLaunches(); // <== THIS THROWS

Why it doesn't work?
What is property 'fetch' of undefined?

Related issue
https://github.com/apollographql/apollo-server/issues/3429

馃К data-sources

Most helpful comment

@rfgamaral Fortunately, the package apollo-datasource-rest works as a standalone, you don't need to pair it exactly with Apollo Server to make it work properly.

Here is an example of use combined with graphql-yoga:

index.js

const { GraphQLServer } = require('graphql-yoga')
const typeDefs = require('./schema');
const resolvers = require('./resolvers');
const theAPI = require('./datasources/api');

const server = new GraphQLServer({ 
    typeDefs,
    resolvers,
    context: () => ({
        dataSources: () => {
            return {
                myAPI: new theAPI(),
            };
        },
    })
})
server.start(() => console.log('Server is running on http://localhost:4000'))

./datasources/api

const { RESTDataSource } = require('apollo-datasource-rest');

class theAPI extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = "https://myexample.com";
    this.initialize({}); // calling initialize() function with empty object is the key
  }

  async getAllData() {
     // return all the data
  }
}

./resolvers

const resolvers = {
  Query: {
    hello: (root, args, context) => {
      return context.dataSources().myAPI.getAllData();
    }
  },
};

module.exports = resolvers;

All 3 comments

Unfortunately, this package does not work as a standalone, you need to pair with Apollo Server to make it work properly (there are workarounds to make it work without Apollo but they are bit cumbersome IMO).

In that same tutorial you linked, you'll eventualy see this:

const { ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const { createStore } = require('./utils');
const LaunchAPI = require('./datasources/launch');
const UserAPI = require('./datasources/user');
const store = createStore();
const server = new ApolloServer({
  typeDefs,
  dataSources: () => ({
    launchAPI: new LaunchAPI(),
    userAPI: new UserAPI({ store })
  })
});

server.listen().then(({ url }) => {
  console.log(`馃殌 Server ready at ${url}`);
});

Look at the dataSources in Apollo Server instance, that's the key.

I wish this packaged was a bit more flexible and configurable to work with other servers and not just Apollo. But that's what we have for the moment. This is not a bug, it's a feature.

@rfgamaral Fortunately, the package apollo-datasource-rest works as a standalone, you don't need to pair it exactly with Apollo Server to make it work properly.

Here is an example of use combined with graphql-yoga:

index.js

const { GraphQLServer } = require('graphql-yoga')
const typeDefs = require('./schema');
const resolvers = require('./resolvers');
const theAPI = require('./datasources/api');

const server = new GraphQLServer({ 
    typeDefs,
    resolvers,
    context: () => ({
        dataSources: () => {
            return {
                myAPI: new theAPI(),
            };
        },
    })
})
server.start(() => console.log('Server is running on http://localhost:4000'))

./datasources/api

const { RESTDataSource } = require('apollo-datasource-rest');

class theAPI extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = "https://myexample.com";
    this.initialize({}); // calling initialize() function with empty object is the key
  }

  async getAllData() {
     // return all the data
  }
}

./resolvers

const resolvers = {
  Query: {
    hello: (root, args, context) => {
      return context.dataSources().myAPI.getAllData();
    }
  },
};

module.exports = resolvers;

For future reference, initialising HttpCache worked for me:

https://github.com/apollographql/apollo-server/issues/2240#issuecomment-508516969

Was this page helpful?
0 / 5 - 0 ratings