What is the best way to store the result from a JavaScript FileReader into a variable for future reference?

I am currently facing an issue uploading a local .json file to my web application. I have managed to display the file in the dev tools, but I am unable to make it accessible for further use. It seems like the problem lies in how I handle (or fail to handle) the asynchronous behavior of the file reader.

Everything is set up in an Angularjs (1.7) environment, which explains the syntax used in the snippet. The goal is to showcase the retrieved data on an openlayers map.

    this.jsonSelected = function(newFile) {
        let reader = new FileReader();
        let result = 'empty';
        reader.readAsText(newFile);
        reader.onload = function(e) {
            result = e.target.result;
            console.log('in onload', result);
            this.result = e.target.result;
        };
        console.log(this.result);
    };

    this.test = function() {
        console.log(this.file);
    }

I anticipated the code to log the file content twice. Once at "console.log ('in onload', result);" and another time at "console.log (this. result);". The first one functions as expected, however, the second one does not. Additionally, the order of logs in the console appears to be inverted, with "console.log (this. result)" showing up before the inload log, as shown in this console screenshot.

I have attempted various modifications, such as switching the names around and adjusting the references to "this.", yet no success. This leads me to believe that I am mishandling the asynchronous data. The details in the screenshot, particularly the timing of the log lines, hint at a timing issue.

Answer №1

After conducting additional research and experimenting with different approaches, I was able to resolve the issue at hand. The code has been modified as follows:

function readFile(newFile) {
    return $q(function(resolve, reject) {
        let reader = new FileReader();
        reader.onload = function(event) {
            resolve(event.target.result);
        };
        reader.onerror = function(event) {
            reject(event);
        };
        reader.readAsText(newFile);
    });
}

this.jsonSelected = function(newFile) {
    readFile(newFile).then(function(data) {
        console.log(data);
        set$scopeFile(data);
    }, function(errData) {

    });
};

Special thanks to Ben for guiding me in the right direction. I was too focused on tackling the asynchronous aspects that I overlooked the scoping issues. If anyone has any reliable resources or documentation on asynchronous JavaScript, I would greatly appreciate it as I continue to struggle with grasping this topic.

I utilized AngularJS's built-in $q service to encapsulate the entire reading process into a promise, which can then be chained with .then.

Answer №2

This is a common issue with asynchronous functions and scoping...

The problem arises when the scope is not set correctly. The this inside the reader.onload function does not refer to the same object as in the console.log(this.result); statement. To fix this, you can either use the bind method or switch to arrow functions.

Additionally, since the onload function is asynchronous, it will execute after the console.log(this.result); call. One way to handle this is by using Promises (such as using $q in AngularJS). Here's an example:

const deferred = $q.defer(); 
deferred.then((data) => { console.log('result', data); });
reader.onload = function(e) {
     result = e.target.result;
     console.log('in onload', result);
     deferred.promise.resolve(e.target.result);
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with displaying value from page in AngularJS modal when clicked

How can I get the data copied from my page's $scope element (thisRequest) into my modal's $scope element (nTask) to display correctly in the modal after clicking a button in AngularJS? You can view the code on this Plunker. Here is an example o ...

Stop aspx button postback on click using cSharp

The following HTML code snippet includes an <asp:Button> element. <asp:Button ID="CalculateG481" runat="server" Text="Calculate" OnClick="CalculateG481_Click" /> When clicked, the button calls the function CalculateG481_Click but then initia ...

Arranging elements based on specific coordinates

const renderTimeSlots = () => { const timeSlots = []; for (let i = parseInt(workStartsAt); i <= parseInt(workEndsAt); i++) { if (i !== 0) { timeSlots.push( <div className="flex flex-row cursor-pointer"> ...

Is there a way to update the href attribute within the script section in vue.js?

I need to dynamically set the href attribute of a link based on data retrieved from a database and rendered in the methods section. <template v-if="header.value == 'ApplicationName'"> <a id="url" href="#" target="_blan ...

Having trouble with tabs in jQuery?

I'm having trouble setting up tabs in a reservation form with 3 tabs that include text boxes for user input. I can't seem to get it working properly and I'm not sure where I've gone wrong. Could it be due to the placement of the content ...

I'm experiencing an issue with Bootstrap 5 where the code runs fine on codeply but not on my local machine

I'm attempting to replicate the scrollspy example found on the Bootstrap website. You can see my attempt here: . Feel free to inspect the code. While the navigation links function correctly, I've noticed that according to Bootstrap's docum ...

What is the best way to modify a CSS property using logical operators in JQuery?

If an element with the class ".has_padding" does not have any text content, it should be set to "display:none;". However, those elements with text inside should remain visible. Below is some code where I have styled the elements to demonstrate the issue. ...

Why must the sidebar be displayed horizontally on the smartphone screen?

I've been struggling to make the sidebar menu on my smartphone display horizontally with icons at the top and text at the bottom. I've tried using flex and other methods, but it still doesn't work sideways. Am I missing something? const s ...

Tips on implementing Dynamic arrays in the useEffect hook within React applications

Does anyone have experience with using a dynamic array as input in the dependency array of the useEffect hook? I'm encountering an issue where the array is being passed as a string and therefore not triggering the hook correctly. const [formData,setFo ...

`Is it common to use defined variables from `.env` files in Next.js applications?`

Next.js allows us to utilize environment variable files such as .env.development and .env.production for configuring the application. These files can be filled with necessary environment variables like: NEXT_PUBLIC_API_ENDPOINT="https://some.api.url/a ...

Ways to trigger an onClick event of one div based on the presence of another div

I'm looking to execute a function when a specific type of button is clicked on my HTML page. I have approximately 10 buttons on the page and I've written the following code to call a function when a button is clicked: $('.divname').ea ...

The simplest way to increase the size of a child element in order to generate a scrollable area

When working with HTML, it's important to consider how the size of a child div affects the parent div. If the child div is larger than its parent, scrollbars will appear on the parent div if the appropriate style rules are set. However, I'm inte ...

Conceal the results of echoing json_encode

One dilemma I encountered was passing an array from PHP to JavaScript using json_encode and ajax. The only method that seemed available was to use echo json_encode($var) This approach printed out the contents of $var on the page due to the echo statement ...

Is there a way to launch a browser in full screen mode using a command line interface?

Is there a clever way to launch a web browser in full screen mode from the command line? The browser's full screen API only activates in response to user interaction. I simply want to show data on a large monitor without any unnecessary elements lik ...

I noticed that when using Next.js with the `revalidate: 1` option on a static page, it is triggering two full F5 refresh actions instead of just one. I was hoping for

Currently, I have set up a blog post edit page in my Next.js project. The post pages are utilizing the Incremental Static Regeneration feature with a revalidation time of 1 second for testing purposes. In the future, I plan to increase this to a revalidat ...

An error message indicating that the page is currently being unloaded has appeared

While working on a NodeJS-ReactJS Isomorphic App, I encountered an issue when clicking on a Link. An error message popped up saying: Uncaught (in promise) Error: Request has been terminated Possible causes: the network is offline, Origin is not allowed by ...

How to dynamically assign a value in a React datepicker component in a React application

Having troubles with react-datepicker? I encountered an issue where setting the value of react-datepicker from props caused it to either not show the value or display a 'wrong time format' error. Here is a snippet of the Datepicker code: this.sta ...

Exploring different ways to make API requests using technologies like jQuery, Angular, and more

I'm new to APIs and I want to create an eco game with Facebook for London and Amsterdam. To do this, I need to obtain data from APIs in each city. After doing some research, I think I can request information on the client side of the app, process it, ...

Attempting to eliminate redundant data retrieved from an XML file being presented on my webpage

I need help deleting duplicate artists that appear when retrieving information from an XML file using JQuery. How can I achieve this? Check out the JS file below: $(function(){ $(window).load(function(){ $.ajax({ url: 'http://imagination ...

Retrieve the initial non-blank line using the head command

Is there a more efficient method to use instead of the head command to locate the first line in a file that contains non-whitespace characters? It seems inefficient to resort to reading the first 100 lines and hoping one of them fits the criteria. I am op ...