Cerin
Cerin

Reputation: 64799

Async Javascript not accessing class method

I'm seeing something weird with some async Javascript accessing a class method.

I have some Javascript that does a fairly intensive search, which can take some time (about 1 minute), so I want to run it asynchronously.

Here's my MVCE:

<html>
    <head>
        <script
              src="https://code.jquery.com/jquery-3.5.1.min.js"
              integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
              crossorigin="anonymous"></script>
    </head>
    <body>
        <div id="search-form">
            <input id="search-terms" type="text" placeholder="enter search terms" />
            <button id="search-button">Search</button>
        </div>
    </body>
    <script type="text/javascript">

        class Index {

            constructor() {
                this.internal_hash = {};
            }

            get_term_count(){
                return Object.keys(this.internal_hash).length;
            }

            do_big_long_expensive_calculation(){
                var i=0;
                for(i=0; i<10000; i++){
                    this.internal_hash[i] = i+1;
                }
                return i;
            }

            search_text(text){
                var results = this.do_big_long_expensive_calculation();
                return results;
            }

        };

        var search_index = new Index;
        var search_results = null;

        $(document).ready(function(){

            async function searchIndex(){
                let text = $('#search-terms').val();
                console.log('searching index for text:'+text);
                console.log('using index with terms:'+search_index.get_term_count());
                search_results = search_index.search_text(text);
                console.log('results:'+search_results.length);
                return search_results;
            }

            $('#search-button').click(function(){
                console.log('search button clicked')
                var el = $(this);
                el.prop("disabled", true);
                el.text('Searching...');
                searchIndex()
                    .then(function(){
                        console.log('search results found:'+(search_results.length));
                        el.text('Search');
                        el.prop("disabled", false);
                    })
                    .catch(reason => console.log(reason.message));
            });

        });
    </script>
</html>

If I call:

 search_index.search_text('sdfssdfsf')

from the browser's console, it returns the expected 10000.

However, if I click the search button, the console.log statement prints out undefined for the value returned by search_index.search_text.

Why is this? The only thing I can think of is there's some characteristic of async I'm not aware of. Does async Javascript not have access to the same memory as the normal synchronous execution model?

Upvotes: 1

Views: 94

Answers (1)

Cagri Tacyildiz
Cagri Tacyildiz

Reputation: 17610

You cant get length of number, return number directly or convert to string and get length

<html>
    <head>
        <script
              src="https://code.jquery.com/jquery-3.5.1.min.js"
              integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
              crossorigin="anonymous"></script>
    </head>
    <body>
        <div id="search-form">
            <input id="search-terms" type="text" placeholder="enter search terms" />
            <button id="search-button">Search</button>
        </div>
    </body>
    <script type="text/javascript">

        class Index {

            constructor() {
                this.internal_hash = {};
            }

            get_term_count(){
                return Object.keys(this.internal_hash).length;
            }

            do_big_long_expensive_calculation(){
                var i=0;
                for(i=0; i<10000; i++){
                    this.internal_hash[i] = i+1;
                }
                return i;
            }

            search_text(text){
                var results = this.do_big_long_expensive_calculation();
                return results;
            }

        };

        var search_index = new Index;
        var search_results = null;

        $(document).ready(function(){

            async function searchIndex(){
                let text = $('#search-terms').val();
                console.log('searching index for text:'+text);
                console.log('using index with terms:'+search_index.get_term_count());
                search_results = search_index.search_text(text);
                console.log('results:'+search_results);
                return search_results;
            }

            $('#search-button').click(function(){
                console.log('search button clicked')
                var el = $(this);
                el.prop("disabled", true);
                el.text('Searching...');
                searchIndex()
                    .then(function(){
                        console.log('search results found:'+(search_results));
                        el.text('Search');
                        el.prop("disabled", false);
                    })
                    .catch(reason => console.log(reason.message));
            });

        });
    </script>
</html>

Upvotes: 1

Related Questions