0

This is not a duplicate question.

It is a request help finding technical conclusion, that is not addressed in How do I return the response from an asynchronous call?

If .then() is not resolving the Promise, how do I track down the problem at that point? It seems like I missed something technically, not conceptually.

This function retrieves data from a URL:

async function getINFO(source, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", source);
    xhr.responseType = "document";
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200){
            var text = xhr.responseXML.getElementsByTagName('pre')[0].innerHTML;
            console.log(text);
            callback(text);
    }
  }
  xhr.send();
}

Externally defined callback:

function asyn_return(input){
  console.log(input);
  return input;
}

The data comes back perfectly in AJAX.

I want to populate an attribute member (datastore.info) with the data.

info is a URL string.

This is the place in the code where I use my AJAX data retrieval function:

if (typeof(info) === 'string'){
// If I have a URL retrieve the data and add it to the datastore object.
    datastore.info = getINFO(info, asyn_return).then(data =>{
      console.log(data);
      return data;
    });
    //console.log(datastore.info);
} else {
    datastore.info = "";
}

console.log(datastore.info);

console.log(data) returns the data I expect, but datastore.info is not populated:

{item1: "data", item2:"data", info: {} }

Not sure what I'm missing technically to have this resolve to the result.

Once I have the promise (the wrapper), what triggers it to resolve? And when that is not happening, what is the likely issue?

Thanks to anyone who can help.

Ken Ingram
  • 1,538
  • 5
  • 27
  • 52

1 Answers1

0

Your console.log at the end is assuming that the data comes un a sync manner, but its is not, therefore it is undefined, cause the ajax data is not arrived yet.

You will need to change your code to be an async one, it can be rewritten via promises or async/await.

It can be written like that:

function getINFO(source) {
  return new Promise(resolve => {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', source);
    xhr.responseType = 'document';
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && xhr.status === 200) {
        var text = xhr.responseXML.getElementsByTagName('pre')[0].innerHTML;
        console.log(text);
        resolve(text);
      }
    };
    xhr.send();
  });
}

if (typeof info === 'string') {
  // If I have a URL retrieve the data and add it to the datastore object.
  getINFO(info).then(data => {
    console.log(data);
    datastore.info = data;
    // continue your async code here
  });
  //console.log(datastore.info);
} else {
  datastore.info = '';
}
felixmosh
  • 32,615
  • 9
  • 69
  • 88
  • Thanks for the Promises example of the async function. Unfortunately, the datastore.info is still undefeined. It pretty much does what it was doing before. It is a bit more organized around the Promise idea though. – Ken Ingram Jun 27 '19 at 00:20
  • You should return that promise, and chain your rest of the code that uses the `datastore` with it. – felixmosh Jun 27 '19 at 07:16
  • Ok. What exactly does that mean? I want the results of the async call to land in datastore.info. Why should I tie in the remaining code, which is independent of that attribute? – Ken Ingram Jun 28 '19 at 07:50
  • if your remaining code depends on the result of the async data, it should be async as well. – felixmosh Jun 28 '19 at 13:05
  • So how do I return the result? console.log(data) sends it to the console. But it does not land in the variable as the command demands datastore.info = (results of async function) – Ken Ingram Jun 28 '19 at 21:40
  • Maybe it is better to learn about async code in JS (promises) – felixmosh Jun 28 '19 at 21:59