0

I'm just working on a small project, here's my code to read the local text file:

function readTextFile(file)
{
    var rawFile = new XMLHttpRequest();
    rawFile.open("GET", file, false);
    rawFile.onreadystatechange = function ()
    {
        if(rawFile.readyState === 4)
        {
            if(rawFile.status === 200 || rawFile.status == 0)
            {
                var allText = rawFile.responseText;
                alert(allText);
            }
        }
    }
    rawFile.send(null);
    return allText;
}

I'm pretty sure I just put the return in the wrong place. Does anyone know where I should put it or could just make a better function overall?

Dah Person
  • 369
  • 1
  • 13
  • `XMLHttpRequest.prototype.onreadystatechange` returns results asynchronously, `allText` may not be defined at `return allText`. See also [Jquery load() only working in firefox?](http://stackoverflow.com/questions/32996001/jquery-load-only-working-in-firefox/) – guest271314 Oct 12 '16 at 03:04
  • nevermind ... you define var allText in the callback function, so it's out of scope when you try to return it – Jaromanda X Oct 12 '16 at 03:06
  • @guest271314 - he's doing a "synchronous" xhr – Jaromanda X Oct 12 '16 at 03:07
  • @JaromandaX Yes, attempted to convey that at previous comment, mentioned how to launch chromium, chrome with flag to request files at `file:` protocole – guest271314 Oct 12 '16 at 03:07
  • @guest271314 - you said the result is asynchronous ... which is the opposite of what he's doing – Jaromanda X Oct 12 '16 at 03:08
  • @JaromandaX The result, or call of `onreadystatechange` is asynchronous. Was comment lacking in clarity? – guest271314 Oct 12 '16 at 03:10
  • NOTE: check your console, if you are using Chrum, it will fail and give the misleading error about cross origin requests - which this clearly isn't – Jaromanda X Oct 12 '16 at 03:10
  • 1
    @guest271314 - no it isn't, if you pass `false` as the third parameter to `.open` - the code works correctly (synchronously) when you fix the scope issue with the `var allText;` - though it still wont work in Chrum due to it's idiotic notion that this is a cross domain request – Jaromanda X Oct 12 '16 at 03:13
  • @JaromandaX Did not notice third parameter at `.open()` call. You can launch chromium, chrome with `--allow-file-access-from-files` flag to use `XMLHttpRequest` to request files at `file:` protocol, see [How do I make the Google Chrome flag “--allow-file-access-from-files” permanent?](http://askubuntu.com/questions/160245/how-do-i-make-the-google-chrome-flag-allow-file-access-from-files-permanent/192996#192996) – guest271314 Oct 12 '16 at 03:23
  • `You can launch chromium, chrome with` - much like other of these special flags, how long before that one disappears too!! :p Though, I can understand why they removed the one that completely disabled honouring CORS responses!! – Jaromanda X Oct 12 '16 at 03:26
  • Those flags will probably not "disappear", they are used, in part, to test chromium, chrome builds. chromium can be built to include the flags; see e.g., chrome://flags. There are many undocumented flags as well. – guest271314 Oct 12 '16 at 03:29
  • @guest271314 for every day users, none of these flags would even be known to them, and in all honesty, many of them should never be used on a browser that has access to the internet! – Jaromanda X Oct 12 '16 at 03:34
  • @JaromandaX _"for every day users, none of these flags would even be known to them"_ ? If the user is asking a Question on stackoverflow regarding to chromium, chrome, they should be aware of the flags the browser they are using. Similarly, when a user posts a Question regarding jQuery, they are expected to have at least reviewed jQuery documentation; or firefox about:config. Though one cannot truly expect anything. fwiw, some of the flags have been maintained and updated for some time at http://peter.sh/experiments/chromium-command-line-switches/ – guest271314 Oct 12 '16 at 03:36

2 Answers2

2

There is no asynchronous issue, the ONLY issue with your code is that you declared allText in the scope of the onreadystatechange callback function

If you declare this var outside of that function, it will work just fine

function readTextFile(file) {
    var rawFile = new XMLHttpRequest();
    var allText; // var declared in readTextFile scope
    rawFile.open("GET", file, false);
    rawFile.onreadystatechange = function () {
        if(rawFile.readyState === 4) {
            if(rawFile.status === 200 || rawFile.status == 0) {
                allText = rawFile.responseText;
            }
        }
    }
    rawFile.send(null);
    return allText; // here you can return the data filled in above
}

Note however, that synchronous XMLHttpRequest in the main thread is deprecated in most browsers - you should learn to embrace asynchronous code. The easiest (and most cross browser currently) method is with callbacks, e.g.

function readTextFile(file, callback) {
    var rawFile = new XMLHttpRequest();
    rawFile.open("GET", file, true); // make it asynchronous
    rawFile.onreadystatechange = function () {
        if(rawFile.readyState === 4) {
            if(rawFile.status === 200 || rawFile.status == 0) {
                callback(rawFile.responseText);
            }
        }
    }
    rawFile.send(null);
}

usage

readTextFile('someFile.txt', function(allText) {
    console.log(allText);
});

A note about CHROME

Chrome - without special command line flag --allow-file-access-from-files for now - will fail regardless, as it produces an error stating that "cross domain requests are only valid for http https ... etc" protocols ... file:/// isn't such a protocol

However, if you've opened the file using file:/// then how can reading a file:/// be cross domain??? Only the developers of Chrum can answer that one

Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • _"Chrome will fail regardless,"_ This is not entirely correct. It is possible to use `XMLHttpRequest` to request file at `file:` protocol using the chromium flags – guest271314 Oct 12 '16 at 03:28
1

Note, chromium, chrome by default do not allow request to file: protocol. You can launch chromium, chrome with flag --allow-file-access-from-files to request files from local filesystem at file: protocol.

You can use callback or Promise, .then() to return .responseText from readTextFile as value of a fulfilled Promise object.

function readTextFile(file) {
  return new Promise(function(resolve, reject) {
    var rawFile = new XMLHttpRequest();
    rawFile.open("GET", file, false);
    rawFile.onreadystatechange = function ()
    {
        if(rawFile.readyState === 4)
        {
            if(rawFile.status === 200 || rawFile.status == 0)
            {
                resolve(rawFile.responseText);
            }
        }
    }
    rawFile.onerror = reject;
    rawFile.send(null);
  })
}

readTextFile("file://path/to/file.txt")
.then(function(text) {
  // `text` : `rawFile.responseText`
  console.log(text);
  alert(allText);
})
// handle error
.catch(function(err) {
  console.log(err)
});
guest271314
  • 1
  • 15
  • 104
  • 177