Why is my GET Request getting hung up in Node using Fetch

140 Views Asked by At

getDocuments request never completes/stays pending. What am I missing?

App.js

import React, { useState, useEffect } from 'react';
import Grid from './Grid';
import apis from '../api/index';

export default function App(props) {

  const [documents, setDocuments] = useState([]);

  useEffect(() => {

    async function initialize() {
      await apis.getDocuments().then(documents => {
        setDocuments(documents.data.data);
      });
    }

    initialize();
  }, []);
    
  return ( <Grid documents={documents} /> )
}

Controller.js

const fetch = require('node-fetch');

exports.getDocuments = async (req, res) => {
  // added 'return' before fetch
  return fetch('EXTERNAL API ENDPOINT', {
    method: 'GET',
    headers: {"api-key": "API KEY"}
  })
  .then(res => res.json())
  .then(json => {
    console.log(json);
    return json
  }).catch(err => console.log(err));
};

also tried this syntax:

//  added cors
exports.getDocuments = async () => {
  console.log("getting documents...");

  const response = await fetch(URL, {
    method: 'GET',
    mode: 'cors',
    headers: {
      "Content-Type": "application/json",
      "x-api-key": "KEY"
    }
  })

  const result = await response.json();
  console.log('result', result);
  return result;

};

server index.js

const express = require('express');
const cors = require('cors');

const { getDocuments } = require('./controllers/Controller');

const router = require('./routes');

const app = express();

//  enable CORS for all origins to allow development with local server
app.use(cors({credentials: true, origin: "http://localhost:3002"}));

app.use('/api', router);

app.get('/', (req, res) => {
    res.send('This is the backend/API');
})

app.set('port', process.env.PORT || 4200);
const server = app.listen(app.get('port'), () => {
  console.log(`Express running on port ${server.address().port}`);
});

enter image description here

with server on localhost: enter image description here

2

There are 2 best solutions below

2
On BEST ANSWER

Assuming getDocuments is added to your /api router like this

router.get("/getDocuments", getDocuments);

Express does not use the return value of route handlers. Instead, you need to send a response.

You need to change your controller to be like the following

exports.getDocuments = async (req, res, next) => {
  console.log("getting documents...");

  const url = "EXTERNAL API ENDPOINT";
  try {
    const response = await fetch(url, {
      headers: {
        "x-api-key": "KEY",
      },
    });

    if (!res.ok) {
      // log details of unsuccessful responses
      console.error(
        "Fetch failed",
        url,
        response.status,
        await response.text(),
      );
      throw new Error("Failed to fetch from upstream");
    }

    //    
    res.json(await response.json()); // send a response
    //   

  } catch (err) {
    // propagate the error to Express' error handlers
    next(err);
  }
};

Note, the try..catch is not required if using Express v5+

0
On

You're missing the return statement before your fetch call, otherwise you're not returning anything