1

I have an asynchronous function that is called when the api is connected to. this should return some json and then it will be displayed on the json response of the page. In the json response I get undefined.

This is the code i am using:

const express = require('express');
const router = express.Router();

const superagent = require('superagent'); 

function getCyrpto(){
    var result;
    superagent.get('https://min-api.cryptocompare.com/data/v2/pair/mapping/exchange?e=Kraken')
    .query({ api_key: 'xxxxxxxx'})
    .end((err, res) => {
      if (err) { return console.log(err); }

      result = res.body;

    });
    setTimeout(() => {
        console.log(result);
        return result;
    }, 2000)

}


router.get('/', (req, res, next) => {
    crypto=getCyrpto()

    setTimeout(()=> {
        res.status(200).json({
        message: 'geting cyrpto',
        apiResponse: crypto
    });

    }, 2500)



});  
Luke Acko13
  • 61
  • 2
  • 9
  • 2
    the `setTimeout` call inside function `getCrypto` should be inside the `.end ({ })` function. Currently, it runs before the async call is completed. – Mehdi Apr 25 '20 at 12:38
  • 1
    Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Mehdi Apr 25 '20 at 12:38
  • Ok but the console.log in set timeout in getCrypto does output the correct data, it outputs the Json of the request(which it should) , I believe the problem is in the router function? – Luke Acko13 Apr 25 '20 at 12:47

1 Answers1

2

The reason it is happeing because your setTimeOut methods runs before your api call get the result and assign it to the result. This is a common problem most of us face when we start to learn concurrency concept.

For example:

console.log("a");
setTimeOut(()=>console.log("b"),1000);
console.log("c");

Output of above function will

a
c
b

this is happening beacause setTimeout function is a promise which means your nodejs will not wait for it to finish before running the next line, it will just process the setTimeout function in background and when it will finish it will call its callback function given as first parameter in setTimeOut.

Your solution should be

function getCyrpto(){
return new Promise((resolve,reject)=>{
     var result;
    superagent.get('https://min-api.cryptocompare.com/data/v2/pair/mapping/exchange?e=Kraken')
    .query({ api_key: 'xxxxxxxx'})
    .end((err, res) => {
      if (err) { console.log(err); reject(err); }
      result = res.body;
      setTimeout(() => {
        console.log(result);
        resolve(result);
    }, 2000)
    });
  }

   router.get('/', (req, res, next) => {
     getCyrpto().then(crypto=>{
          setTimeout(()=> {
        res.status(200).json({
        message: 'geting cyrpto',
        apiResponse: crypto
    },2500);
  }).catch(err=>{res.status(400).json(err)})
}
Abhinav Singh
  • 302
  • 3
  • 15