javascriptminimizereducing

"Outsource" recurring code into a function with parameters (js)


so i use one js file to load multiple html and js files whenever they are needed. I have a working code for plenty modules. In the example below you can see the first two modules. All of them look exactly the same. Now i want to "outsource" recurring code into a function with parameters so that the code-amount overall gets minimized. Since i have never done something like this before i could need some help (i am learning js at the moment). I would realy appreciate some help.

 //first module
 if (moduleID === "placeone") {
            var isLoaded = 0;
            if (isLoaded) {
                console.log("file already loaded");
                returnValue = new PlaceOneModule(id, moduleInitialData);
            }
            $("#placeone").load("html/modules/PlaceOneModule.html", function (response, status, xhr) {
                console.log("PlaceOneModule.html" + " " + status);
                $.getScript("js/modules/PlaceOneModule.js").done(function () {
                    console.log("PlaceOneModule.js geladen");
                    isLoaded = 1;
                    returnValue = new PlaceOneModule(id, moduleInitialData);
                }).fail(function () {
                    console.log("PlaceOneModule.js nicht geladen");
                });
            });
        }

    //second module
        if (moduleID === "placetwo") {
            var isLoaded = 0;
            if (isLoaded) {
                console.log("file already loaded");
                returnValue = new PlaceTwoModule(id, moduleInitialData);
            }
            $("#placetwo").load("html/modules/PlaceTwoModule.html", function (response, status, xhr) {
                console.log("PlaceTwoModule.html" + " " + status);
                $.getScript("js/modules/PlaceTwoModule.js").done(function () {
                    console.log("PlaceTwoModule.js geladen");
                    isLoaded = 1;
                    returnValue = new PlaceTwoModule(id, moduleInitialData);
                }).fail(function () {
                    console.log("PlaceTwoModule.js nicht geladen");
                });
            });
        }

Solution

  • The question is rather complex to answer, as there are many things to account for.

    var cache = {};
    
    function module(name, target, done) {
        if (!(name in cache)) {
            return $(target).load('html/modules/' + name + '.html', function(response, status, xhr) {
                console.log(name + '.html ' + status);
    
                $.getScript('js/modules/' + name + '.js')
                    .done(function() {
                        console.log(name + '.js geladen');
                        cache[name] = window[name];
    
                        done(null, cache[name]);
                    })
                    .fail(function() {
                        var message = name + '.js nicht geladen';
    
                        cache[name] = function() {
                            console.error(message);
                        };
    
                        done(message);
                    });
            });
        }
    
        setTimeout(function() {
            done(null, cache[name]);
        }, 0);
    }
    

    I'll try to explain my train of thought behind this:

    So, how to use this? It now boils down to calling the module function

    module('#placeone', 'PlaceOneModule', function(error, PlaceModule) {
      if (error) throw new Error(error);
    
      var instance = new PlaceModule(id, initial);
    
      // ...
    }
    

    I have used the common function(error, value) {..} signature for the callback function, which always has the error as first argument (allowing for other arguments to be added and made optional).

    There are some caveats/assumptions worth mentioning:

    This has become a rather elaborate answer, I hope I explained every step involved sufficiently.