0

I am trying to create a function that returns the contents of a txt file using JavaScript so it can be stored in a variable and used at a later time. So far I have tried:

var text;

function getText(url) {
  fetch(url)
    .then( r => r.text() )
}

getText("foo.txt").then(r => text);

but this says that text is undefined.

I have also tried:

function getText(url) {
  var client = new XMLHttpRequest();
  client.open('GET', url);
  client.onreadystatechange = function() {
    text = client.responseText;
    return text;
  }
  client.send();
}

This still gives me undefined. If I put a console.log() inside the readystatechange it gives the right text but repeats it twice.

I have also tried:

function getText(url) {
    jQuery.get(url, function(data) {
        console.log(data);
    });
    return data;
}

but this gives me an error saying jquery is not defined and I can't seem to get jQuery to work so preferably is there anyway to do this without jquery?

Tori Harris
  • 563
  • 2
  • 7
  • 21
  • 2
    Of course `text` is undefined. Try `.then(r => console.log(r));` instead. – Andy Jan 19 '19 at 16:29
  • `text` is undefined. `r` is not. Use ``.then(text => { /* use `text` here */ })`` instead. – Bergi Jan 19 '19 at 16:29
  • @Andy `console.log()` just prints it to the console, is there anyway to store it in the variable? – Tori Harris Jan 19 '19 at 16:34
  • @Bergi I tried that but it still gives me undefined – Tori Harris Jan 19 '19 at 16:49
  • @ToriHarris *Where* did it give you `undefined`? Notice that [you cannot assign the result to the global `text` variable and expect to be able to work with that immediately after starting the request](https://stackoverflow.com/q/14220321/1048572) – Bergi Jan 19 '19 at 16:55

2 Answers2

0

The first approach using the fetch API is rightly returning undefined as you are not returning the thenable. Note that the return value itself is a promise and not the data, you need to call then() to log the data. Currently there is no way to assign the returned data directly to a variable.

As for the second example if you put the console.log in the client.onreadystatechange of course it will log the response twice as it gets called multiple times for a single request. You should only log the response when the response code is 200 OK and state is complete with a value of 4.

function getText(url) {
     return fetch(url) //notice the return, it is returning a thenable
            .then(text => text.text())
}
getText("https://jsonplaceholder.typicode.com/todos/1").then(d => console.log(d));

//Using Async/Await

async function getTextAsync(url) {
     let text = await fetch(url)
     let data = await text.text()
     return data;
}
getTextAsync("https://jsonplaceholder.typicode.com/todos/1").then(d => console.log(d));

//Using XMLHttpRequest

function getTextXml(url) {
  var client = new XMLHttpRequest();
  client.open('GET', url);
  client.onreadystatechange = function() {
  if (client.readyState == 4 && client.status == 200) //notice the response code and the state code
   {
    if (client.responseText)
     {
       console.log(client.responseText);
     }
    }
   }
  client.send();
}
getTextXml("https://jsonplaceholder.typicode.com/todos/1");
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
-1

console.log() just prints it to the console, is there anyway to store it in the variable?

Because fetch is an async process you will never be able to assign a value to text like that. The closest you can get with modern browsers at the moment is to use async/await.

// Mock `fetch` to return a value after 1.5s 
function getText(url) {
  return new Promise(resolve => {
    setTimeout(() => resolve('Hallo'), 1500);
  });
}

// Unfortnately `await` has to be used in conjunction
// with async so we have to use an immediately-invoked 
// async function expression here
(async () => {

  // `await` for the promise to resolve
  const text = await getText("foo.txt");
  console.log(text);
})();
<p>Please wait 1.5s</p>

There's a lot more information (which will take a while to distill) in the answers to this Stackoverflow question.

Andy
  • 61,948
  • 13
  • 68
  • 95