Home > Software engineering >  Uncaught in promise while waiting for json response
Uncaught in promise while waiting for json response

Time:12-28

I'm implementing Promises for the first time in JS and am getting uncaught in promise exception in console log while running the below code.

function data_present() {
        return new Promise((resolve, reject) => {
            fetch(api)
            .then(response => response.json())
            .then(message => { 
                console.log(message)
                if(message && Object.keys(message).length != 0) {
                    resolve()
                }
                else {
                    reject()
                }
            })
        })
    }

I am handling the result of the promise return value in the main function as below and am yet getting the uncaught in promise message:

function main() {
    data_present().then(() => {
        load_graph()
    }).catch(() => {
        data_present()
    })
}

The logic behind the data_present() is to wait till we get a non-empty JSON response at the API endpoint and keep polling it if JSON response is empty.

The exception I'm getting is as follows:

Uncaught (in promise) undefined
(anonymous) @ index.js:34
Promise.then (async)
(anonymous) @ index.js:29
data_present @ index.js:26
(anonymous) @ index.js:56
Promise.catch (async)
getParametersData @ index.js:55
onclick @ (index):92

CodePudding user response:

You might think about having one function to get, parse, and return the JSON from the API (no need to wrap your fetch in a promise as it already returns one), and use your polling function to check the returned data. If it's correct call one function, otherwise poll getData again. If there's an API error log that instead.

I've used async/await here but the principles are the same.

// Simulates an API
// If the random number is a modulo of 5 set data
// to an object with a key/value pair, otherwise
// it set it to an empty object. If the random number
// is a modulo of 9 send an error, otherwise send the data.
function mockFetch() {
  return new Promise((res, rej) => {
    const rnd = Math.floor(Math.random() * 20);
    const data = rnd % 5 === 0 ? { name: 'Bob' } : {};
    setTimeout(() => {
      if (rnd % 9 === 0) rej('Connection error');
      res(JSON.stringify(data));
    }, 2000);
  });
}

// `getData` simply gets a response from the API and parses it.
// I had to use JSON.parse here rather that await response.json()
// because I'm not using the actual fetch API.
async function getData() {
  const response = await mockFetch();
  return JSON.parse(response);
}

// The `poll` function does all the heavy-lifting
// first we initialise `count`
async function poll(count = 1) {

  console.log(`Polling ${count}`);

  // Try and get some data. If it's not an empty object
  // log the name (or in your case call loadGraph),
  // otherwise poll the API again after two seconds.
  // We wrap everything in a `try/catch`.
  try {

    const data = await getData();

    if (data && data.name) {
      console.log(data.name); // loadGraph
    } else {
      setTimeout(poll, 2000,   count);
    }

  // If the API sends an error log that instead
  // and poll again after five seconds
  } catch (err) {
    console.log(`${err}. Polling again in 5 seconds.`);
    setTimeout(poll, 5000, 1);
  }

}

poll();

And here's the version based on Dai's answer:

function mockFetch() {
  return new Promise((res, rej) => {
    const rnd = Math.floor(Math.random() * 20);
    const data = rnd % 5 === 0 ? { name: 'Bob' } : {};
    setTimeout(() => {
      if (rnd % 9 === 0) rej('Connection error');
      res(JSON.stringify(data));
    }, 2000);
  });
}

async function getData() {
  const response = await mockFetch();
  return JSON.parse(response);
}

async function delay(time) {
  return new Promise(res => setTimeout(res, time));
}

async function poll(count = 1) {

  do {

    console.log(`Polling ${count}`);

    try {
      const data = await getData();
      if (data && data.name) return data;
      await delay(2000);
    } catch (err) {
      console.log(`${err}. Polling again in 5 seconds.`);
      await delay(5000);
    }

      count;

  } while (count < 10);

  console.log(`Reached poll limit - ${count}.`);
  return false;

}

async function main() {
  console.log('First');
  console.log(await poll());
  console.log('Second');
}

main();

CodePudding user response:

Also fetch already returns a promise. So you shouldnt wrap it again (I included this in my example). The error comes from the second call to the function as described in the second catch block below

function data_present() {
  return fetch(api)
    .then(response => response.json())
    .then(message => {
      console.log(message)
      if (!message || Object.keys(message).length === 0) {
        throw new Error('something went wrong');
      } 
    })
}

function main() {
  data_present()
    .then(() => {
      load_graph()
    }).catch(() => {
      return data_present() // the promise which is returned here was not caught in your example
    })
    .catch(() => {
      // another error
    })
}

  • Related