Loadrunner
 Dependency Management,
      Script Loader
An Introduction
Events
Every JavaScript developer is familiar with
Events.
"When X happens, do Y"

X.bind('happens', function() {
    Y();
});
Dependencies
A Dependency says:
"Wait for X before doing Y"
Yes, ok,
that sounds the same.
Wait for X before doing Y

Two key differences:
   1. Y only gets fired once.
   2. If X has already happened, Y fires
      immediately.
You are already familiar with this behaviour
for “document ready”.
Script Loading
Script loading is a type of Dependency
Problem.
For example,
"Wait for jQuery before doing Ajax"
This could be rephrased as:
"using jQuery, do Ajax"
using

Loadrunner specifies dependencies with the
using function:


using('/lib/jquery.js',
   function() {
     $.ajax({ … });
   }
);
using(multiple)

We can depend on multiple scripts this way:


using(
   '/lib/jquery.js',
   ‘plugin.js’,
   function() {
     $.ajax({ … });
   }
);
using(sequence)
We can also require that scripts are loading
in sequence, by passing an array.
eg., Load jQuery, then jQuery UI.
using([
   '/lib/jquery.js',
   ‘/lib/jquery.ui.js‘
   ],
   function() {
      $.ajax({ … });
   }
);
Asynchronous
Since Loadrunner has to wait for the
dependencies to be fulfilled, the "using"
function makes your code asynchronous.
console.log(1);
using('/lib/jquery.1.7.js',
   function() {
     console.log(2);
   }
);
console.log(3);
// => 1, 3, 2
[Asynchronous]
Unless the scripts have already been loaded.

using('/lib/jquery.1.7.js',
   function() {
     console.log(1);
     using('/lib/jquery.1.7.js',
     function() {
       console.log(2);
     }
     console.log(3);
   }
);
// => 1, 2, 3
Awesome?

This script dependency loader is awesome,
but we can see two problems with it.
1. Scripts must load into the global scope.
2. It waits for the script to load, but does
   not wait for the functions to be ready.
For example, if ‘api.js’ is:

using('/lib/jquery.1.7.js',
  function() {
     window.api = {};
     api.wizardry = function() {
        alert('Wahoo');
     };
  })
});

The ‘api’ won’t be ready when we want it:

using('/js/api.js', function() {
  api.wizardry();
});
“ReferenceError: api is not defined”
API ready
Besides script loading, there are lots of
reasons why the API might take time to be
ready:
•   Creating DOM nodes, like iframes.
•   Ajax communications
•   setTimeouts
•   Animation
Modules

We can solve these problems by wrapping
our scripts as Loadrunner "modules".


To create a module, we wrap our script in a
provide function.
For example:
provide(function(exports) {
  using('/lib/jquery.1.7.js',
    function() {
      var api = {};
      api.wizardry = function() {
         alert('Wahoo');
      };
      exports(api);
    });
  });
});
The provide function uses exports to declare
when it is ready, and return the object it
created.
We can now depend on the result of this
module in our using statement:
using.path = '/js';
using('api', function(api) {
  api.wizardry();
});

We state the dependency in a different way:
we leave off the ".js" extension to tell
Loadrunner that we want a module.
The callback function receives a parameter
api that contains the result of the module's
exports object.
Win
Modules make life really easy.

using(‘sizzle’,'api',‘animation’,
   function($, api, anim) {
     anim($(‘#thing’), api.text);
   }
);
Collecting params
If you like, you can collect parameters

using(‘sizzle’,'api',‘animation’)
  .as(
     function(all) {
       all.animation(all.api.text);
     }
  );
Collecting params
Or mix techniques

using(‘sizzle’,'api',‘animation’)
  .as(
     function(all, $, api, anim) {
       all.animation(api.text);
     }
  );
Module-ify
Scripts like jQuery aren’t provided as
modules, but we can make a module that
takes advantage of their noConflict mode.

provide(function(exports) {
  using(‘/lib/jquery.js’,
     function() {
       exports(jQuery.noConflict());
     }
  );
});
Folders
Modules can make our JS folder readable.

>ls
loadrunner.js
lib/jquery.js
imports/jquery.js
api/api.js
api/iframe_loader.js
anim/animation.js
HTML
Loadrunner can be loaded with data
attributes.
<script src=”loadrunner.js”
 data-path=”/js”
 data-main=”main.js” />

Path is the folder of your Loadrunner
modules (defaults to path containing
loadrunner.js).
Main is the first script to execute.
Summary
• Use Loadrunner modules as much as you
  can.

• Only export your module when it’s ready.
• Watch out for asynchronous functions.
Go forth and load.

Loadrunner

  • 1.
  • 2.
  • 3.
    Events Every JavaScript developeris familiar with Events. "When X happens, do Y" X.bind('happens', function() { Y(); });
  • 4.
  • 5.
  • 6.
    Wait for Xbefore doing Y Two key differences: 1. Y only gets fired once. 2. If X has already happened, Y fires immediately. You are already familiar with this behaviour for “document ready”.
  • 7.
    Script Loading Script loadingis a type of Dependency Problem. For example, "Wait for jQuery before doing Ajax" This could be rephrased as: "using jQuery, do Ajax"
  • 8.
    using Loadrunner specifies dependencieswith the using function: using('/lib/jquery.js', function() { $.ajax({ … }); } );
  • 9.
    using(multiple) We can dependon multiple scripts this way: using( '/lib/jquery.js', ‘plugin.js’, function() { $.ajax({ … }); } );
  • 10.
    using(sequence) We can alsorequire that scripts are loading in sequence, by passing an array. eg., Load jQuery, then jQuery UI. using([ '/lib/jquery.js', ‘/lib/jquery.ui.js‘ ], function() { $.ajax({ … }); } );
  • 11.
    Asynchronous Since Loadrunner hasto wait for the dependencies to be fulfilled, the "using" function makes your code asynchronous. console.log(1); using('/lib/jquery.1.7.js', function() { console.log(2); } ); console.log(3); // => 1, 3, 2
  • 12.
    [Asynchronous] Unless the scriptshave already been loaded. using('/lib/jquery.1.7.js', function() { console.log(1); using('/lib/jquery.1.7.js', function() { console.log(2); } console.log(3); } ); // => 1, 2, 3
  • 13.
    Awesome? This script dependencyloader is awesome, but we can see two problems with it. 1. Scripts must load into the global scope. 2. It waits for the script to load, but does not wait for the functions to be ready.
  • 14.
    For example, if‘api.js’ is: using('/lib/jquery.1.7.js', function() { window.api = {}; api.wizardry = function() { alert('Wahoo'); }; }) }); The ‘api’ won’t be ready when we want it: using('/js/api.js', function() { api.wizardry(); }); “ReferenceError: api is not defined”
  • 15.
    API ready Besides scriptloading, there are lots of reasons why the API might take time to be ready: • Creating DOM nodes, like iframes. • Ajax communications • setTimeouts • Animation
  • 16.
    Modules We can solvethese problems by wrapping our scripts as Loadrunner "modules". To create a module, we wrap our script in a provide function.
  • 17.
    For example: provide(function(exports) { using('/lib/jquery.1.7.js', function() { var api = {}; api.wizardry = function() { alert('Wahoo'); }; exports(api); }); }); }); The provide function uses exports to declare when it is ready, and return the object it created.
  • 18.
    We can nowdepend on the result of this module in our using statement: using.path = '/js'; using('api', function(api) { api.wizardry(); }); We state the dependency in a different way: we leave off the ".js" extension to tell Loadrunner that we want a module. The callback function receives a parameter api that contains the result of the module's exports object.
  • 19.
    Win Modules make lifereally easy. using(‘sizzle’,'api',‘animation’, function($, api, anim) { anim($(‘#thing’), api.text); } );
  • 20.
    Collecting params If youlike, you can collect parameters using(‘sizzle’,'api',‘animation’) .as( function(all) { all.animation(all.api.text); } );
  • 21.
    Collecting params Or mixtechniques using(‘sizzle’,'api',‘animation’) .as( function(all, $, api, anim) { all.animation(api.text); } );
  • 22.
    Module-ify Scripts like jQueryaren’t provided as modules, but we can make a module that takes advantage of their noConflict mode. provide(function(exports) { using(‘/lib/jquery.js’, function() { exports(jQuery.noConflict()); } ); });
  • 23.
    Folders Modules can makeour JS folder readable. >ls loadrunner.js lib/jquery.js imports/jquery.js api/api.js api/iframe_loader.js anim/animation.js
  • 24.
    HTML Loadrunner can beloaded with data attributes. <script src=”loadrunner.js” data-path=”/js” data-main=”main.js” /> Path is the folder of your Loadrunner modules (defaults to path containing loadrunner.js). Main is the first script to execute.
  • 25.
  • 26.
    • Use Loadrunnermodules as much as you can. • Only export your module when it’s ready. • Watch out for asynchronous functions.
  • 27.