1
\$\begingroup\$

I'm writing some code to return results from a web service and display them on screen. If the service is down I want to use Lawnchair to serve cached results.

<h2>Test</h2>
<p>Click to load!</p>
<button class="btn" type="button" onclick="loadData()">Load</button>
<div id="results"></div>

@section scripts{
    <script>
        $(function () {
            // I'm called on window load and am an inner scope to the window as a whole.
            // Store is only accessible to sub functions of my scope.
            var store = new Lawnchair(function () { });

            // Store in the window, it's the only way to reach it.
            window.store = store;
        });

        // I'm in the root scope and only have access to globals.
        function loadData() {
            $.ajax({
                url: '/api/customer/GetAll',
                data: '',
                type: 'GET'
            }).done(function (data) {
                storeData(data);
                drawData();
            })
                .fail(function (err) {
                    alert('Data unavailable, server responded with: ' + err.status);
                    drawData();
                });
        }

        function storeData(data) {
            window.store.save({ key: 'data', value: data });
        }

        function retrieveFromStore() {
            var data;
            window.store.get('data', function (d) { data = d.value; });
            return data;
        }

        function drawData() {
            var data = retrieveFromStore();
            var text = '';
            for (var i = 0; i < data.length; i++) {
                text += '<p>' + data[i].Name + '</p>';
            }
            $('#results').append(text);
        }
    </script>
}

As you can probably tell I'm very new to JavaScript and concepts of variable scope and callback functions.

I'd like some general JavaScript feedback but more specifically how to avoid globals. I understand they're evil in every language but do they seem to be unavoidable here?

While this code works and retrieves data, the approach to getting the data from my Lawnchair cache seems wrong. Is there a better way than in the method retrieveFromStore()?

\$\endgroup\$
1
\$\begingroup\$

Closures in JavaScript

I'd like some general JavaScript feedback but more specifically how to avoid globals. I understand they're evil in every language but do they seem to be unavoidable here?

You can easily avoid globals in JavaScript using closures. I suggest to read more about the subject, for example in this article by Douglas Crockford.

In fact you have already used the concept here:

function retrieveFromStore() {
    var data;
    window.store.get('data', function (d) { data = d.value; });
    return data;
}

The anonymous function in the call to store.get uses the data variable defined outside of the function, but within its closure.

As another example, and a simple solution to avoid window.store, you could define all your functions within the outer $(function () { ... });, and then store will be visible to them, for example:

$(function () {
    var store = new Lawnchair(function () { });

    function storeData(data) {
        store.save({ key: 'data', value: data });
    }

    // ... other functions
});

Append directly instead of accumulating text

This function accumulates text in a variable before appending to the dom:

function drawData() {
    var data = retrieveFromStore();
    var text = '';
    for (var i = 0; i < data.length; i++) {
        text += '<p>' + data[i].Name + '</p>';
    }
    $('#results').append(text);
}

This is unnecessary, you could append directly:

function drawData() {
    var data = retrieveFromStore();
    var results = $('#results');
    for (var i = 0; i < data.length; i++) {
        results.append('<p>' + data[i].Name + '</p>');
    }
}

Note that the reason for var results = $('#results'); is to avoid repeated dom lookups, which can be expensive. It's a good practice to save repeatedly used dom lookups in variables.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.