JavaScript modularity with RequireJS (from spaghetti code to ravioli code)

http://netmvc.blogspot.com/2012/11/javascript-modularity-with-requirejs.html

Today I would like to describe how you can make your JavaScript code much much much better.

We know a lot about how to make our c# code much better. And we always use it.
We split out our c# code to classes, put the classes to modules, put the modules to layers, etc.

But we never do the same for our JavaScript code. And this is a big mistake.

And that's why we have a lot of Spaghetti Code inside our apps.

The main problems with function spaghetti code are:

  • It's really hard to figure out where the one block of code begins and where the other ends
  • Who's responsible for what?
  • How are we deal with global scope pollution (e.g. use the same variables in different pieces of code)
  • Low code re-use
  • Not easy to maintain, test and debug.


I'm not going to describe in details what the functional spaghetti code is, because you can find a lot of references in the Internet.
I would like to show here how to avoid it and make your code better using RequireJS.

 

 

 

 RequireJS

The following command in the Package Manager console will install RequireJS package into your ASP.NET application:

PM > Install-Package RequireJS


RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.

In other words RequireJS really helps:

  • To define our modules
  • To resolve module dependencies
  • To load scripts in the proper order (and asynchronously)


So, RequireJS really helps to define a structure to the modules in a JavaScript applications.

 

 RequireJS modules

First I would like to show how you can create modules using RequireJS.
I will use the same example as I used to show how to create a JavaScript module.

复制代码
define('messenger',
    ['jquery'],
    function ($) {
        var text = 'I am a module',
            showMessage = function() {
                $("#messagebox").html(text);
            };
 
        return {
            showMessage: showMessage
        };
    }
);
复制代码

It looks as easy as a JavaScript module. But I would like to describe some differences.
The RequireJS module starts with:

define('messenger',

Where 'messenger' is the module ID. You can use this ID if you want to reference this module in other modules.

The next line describes dependencies of this module:

['jquery'],
In this example our module depends on jQuery only.

And then you have to specify module body as a function.

As you can see it's really simple to create a module using RequireJS.
 

 Using RequireJS

Let's change all of our modules.
config.js
复制代码
define('config', //module id
    [], //no dependency
    function () {
        var baseUrl = '/api/messenger/';
 
        return {
            baseUrl: baseUrl
        };
    }
);
复制代码

dataservice.js

复制代码
define('dataservice',  //module id
    ['jquery', 'config'],  //depend on two other modules
    function ($, config) {
        var
            callApi = function (url, type, callback) {
                $.ajax({
                    url: url,
                    type: type,
                    dataType: 'json',
                    success: function (data) {
                        callback(data);
                    }
                });
            },
             
            getMessage = function (id, callback) {
                url = config.baseUrl + id;
                callApi(url, 'GET', callback);
            };
 
        return {
            getMessage: getMessage
        };
    }
);
复制代码

messager.js

复制代码
define('messenger',   //module id
    ['jquery', 'dataservice'],  //depend on two modules
    function ($, dataservice) {
        var showMessage = function (id) {
            dataservice.getMessage(id, function (message) {
                $("#messagebox").html(message);
            });
        };
 
        return {
            showMessage: showMessage
        };
    }
);
复制代码

main.js

复制代码
(function() {
    requirejs.config(
        {
            paths: {
                'jquery': '../Scripts/jquery-1.8.2.min'
            }
        }
    );
 
    require(
        ['messenger'],
        function(messenger) {
            var id = 55;
            messenger.showMessage(id);
        }
    );
})();
复制代码

All of the modules look as they were before, except of main module.

In this module I have configured RequireJS to specify where RequiteJS can find the jquery module.

requirejs.config(
    {
        paths: {
            'jquery': '../Scripts/jquery-1.8.2.min'
        }
    }
);

After all, we have to change our HTML to load our modules.

index.html

复制代码
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Phase 1</title>
</head>
<body>
    <div>
        <h1>Modular Demo 1</h1>
    </div>
    <div id="messagebox"></div>
 
    <script data-main="main" src="../Scripts/require.js" type="text/javascript"></script>
    
</body>
</html>
复制代码

Small remarks about our HTML changes.

We should not load any of our modules or jQuery, because RequireJS will handle it for us.
We have to load RequireJS only, and specify 'data-main' attribute, which tells RequireJS to load main.js script after RequireJS loads. In other words, we specify start up script in 'data-main' attribute.

And after all RequireJS does the 'magic' and loads all of our modules in proper order automatically.

As a result, our code becomes much much better now, as I promised at the beginning of this post.

That's all. And see you next time.

 

 
 

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(247)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2017-06-26 ISheet ICell
2014-06-26 委托的begininvoke
2014-06-26 C# 给某个方法设定执行超时时间
2014-06-26 C#中的Invoke----control上的以及delegate的是不一样的
点击右上角即可分享
微信分享提示