[dojo-contributors] deferredRequire extension

Ken Benjamin kenbenjamin at kenbenjamin.net
Sat Jun 2 04:20:26 EDT 2012


How about this, which extends all instances of require() to have
require.dynamic(). Parameters are the same as for require() excluding a
callback but the return is a Deferred.

Proposed dojo/_base/dynamic.js:

require(['dojo/_base/Deferred'], function(Deferred){
	require.prototype.constructor.dynamic = function(
		config,       //(object, optional) hash of configuration
properties
		dependencies //(array of commonjs.moduleId) list of
modules to be loaded before applying callback
	){
		var d = new Deferred();
		var callback = function(){
d.resolve(Array.prototype.slice.call(arguments)); }; // callback Deferred
with list of modules		
		require.apply(this, (config instanceof Array) ? [config,
dependencies, callback] : [dependencies, callback]);
		return d;
	};
});

Example use:

require([
		'require', // local context require
		'dojo/_base/dynamic'
	],
	function(require){
		var widgets = ['dijit/form/Button', 'dijit/form/Textbox'];
		require.dynamic(widgets).then(function(Button, Textbox){
			// do something with Button and Textbox
		});
	}
);
	
I'll update my enhancement ticket, fix the inline documentation, and add a
couple of test cases if folks like this solution.

By the way, in my original code, the sync option doesn't work. I've
removed it in favor of letting require() handle sync as it does now (per
dojo.config settings).

As for implementing it in dojo.js, assuming that is desirable, my
suggestion would be to have a dojo.config option to conditionally load it.
Something like: allowDynamicRequires: true.

Sasha, In practice you will still want to require(['require'],
function(require){} in modules to get the local require context, as
documented in dojo loader. The other solution is to pass the dojo.config
object in your require.dynamic() call:

var req = require.dynamic(dojo.config, ['dep1']);

I think that with dojo eventually going to baseless instantiation (i.e. no
dojo.* globals) that the require(['require']) approach will be simplest
and fastest. It is not a lot to type. It's also much faster to run than
forcing require to parse the configuration parameters again.

Ken

P.S. Yes, I have a CLA on file. Thanks, Colin, for the eSign.



-----Original Message-----
From: Sasha Firsov [mailto:suns at firsov.net]
Sent: Saturday, June 02, 2012 5:10 AM
To: dojo dev.
Cc: Ken Benjamin
Subject: deferredRequire extension

Foloving http://bugs.dojotoolkit.org/ticket/15445, I am trying to make
Deferred implementation of require
with same signature and semantics as original.
Since 8kb of Deferred not necessary fit into 'nano' and to make
acceptance easier, initial draft meant to be external module rather
patch to dojo.js

Is there the way of original require() runtime patching?

Unfortunately I was not able to find one. The require returned by module
definition
     define(["require"],function(require)
is closure-based and used for current module reference for relative path
negotiation.

Since closure content is different for each module, the one which is
retrieved from in deferredRequire module has no use for relative pathes
of caller.
Which on one side forced me to pass module require as extra parameter
and forces user to add "require" as additional dependency:

define( ["deferredRequire","require"], function( dr, require )
{
     dr(require).require( ["../myMod"] )
         .than( function(myMod){ ... })
         .fail(function errback(){ });
});

Which is working but kind of ugly.
Is there a way to alter original require behavior?
JS aspect on require function, AMD pluging, etc?

Patch of dojo.js seems easier :)

Cheers,
Sasha


More information about the dojo-contributors mailing list