Opened 8 years ago

Closed 8 years ago

#15445 closed enhancement (invalid)

Dynamic (runtime) require() function [cla]

Reported by: kbenjamin Owned by: Rawld Gill
Priority: undecided Milestone: tbd
Component: Loader Version: 1.7.2
Keywords: Cc:
Blocked By: Blocking:

Description

Since require() does not provide an easy method to load modules on the fly, I built a module that does so. It's based, in part, on Kitson's work in the 1.8 parser but is generalized for other usage scenarios.

The code is quite small and this seems like a useful feature to have. I know I've wanted it, obviously Kitson felt the parser needed it, and also Karl Tiedt wanted the same, just to name a few potentially interested parties.

See the attached dynamicRequire.js for documentation and details.

Attachments (2)

dynamicRequire.js (2.8 KB) - added by kbenjamin 8 years ago.
dynamicRequire - load modules during program runtime
dynamicRequire.2.js (2.4 KB) - added by kbenjamin 8 years ago.
Revised and improved dynamicRequire module

Download all attachments as: .zip

Change History (10)

Changed 8 years ago by kbenjamin

Attachment: dynamicRequire.js added

dynamicRequire - load modules during program runtime

comment:1 Changed 8 years ago by Karl Tiedt

You should remove your global dojo reference ;) It should probably be dojo/_base/kernel and kernel.global?

comment:2 in reply to:  1 Changed 8 years ago by kbenjamin

Replying to ktiedt: Thanks. I was wondering what the solution would be going into baseless.

In the meantime, however, I've changed the code to simplify it. See the revised attachment.

Let me also clarify one point that came up:

I am NOT suggesting that this code be integrated into the standard dojo.js.

It's too extra with the Deferred built in. I think it might make a nice add-on or be a configuration option.

Changed 8 years ago by kbenjamin

Attachment: dynamicRequire.2.js added

Revised and improved dynamicRequire module

comment:3 Changed 8 years ago by bill

Since require() does not provide an easy method to load modules on the fly

Of course it does:

require(listOfModules, callback)

It sounds like what you are really campaigning for is a require-like function that returns a Deferred?

(Your patch also has a "sync" flag, but that really doesn't make sense since everything in the AMD world is asynchronous. Synchronous loading is something the legacy dojo did.)

comment:4 Changed 8 years ago by Sasha Firsov

What about implementation which upgrades original require without the need for new syntax?

   define([ "defferedAmdRequire!require"], function( require ){
       require( ["./myModule"  ,"../anotherModule"])
        .then( function(mod1,mod2){}, function errLoading(ex){} );
   });

test :http://simulationlabs.com/dojo/DojoPlay2012/libcommon/DTK1.7/util/doh/runner.html?testModule=lib/AMD/test/defferedAmdRequireTest&paths=lib,../../../lib sourse:http://simulationlabs.com/dojo/DojoPlay2012/lib/AMD/defferedAmdRequire.js

comment:5 in reply to:  3 Changed 8 years ago by kbenjamin

Bill, I had the same thought when I awoke this morning so I tested it in my app by forcing all the dijit modules it uses in my view builder to load on demand, rather than the usual way using define(). It failed except when I used a Deferred to wrap the require.

I've been thinking about why a Deferred solves the problem and the answer is that I think it's an issue of load order.

The app I'm building constructs its view elements dynamically from a database definition but since the elements are hierarchical, i.e. BorderContainer?->ContentPane?->Form->Textbox, I'm doing the require()'s on the fly in a one-by-one process.

Since require does its callback async, I can't guarantee that callback to make Form happened before the one where I create and attempt to place Textbox in Form.

A more curious question has just occurred to me as I write this: why does wrapping each require inside its own Deferred solve the problem? (And it does). The Deferred is created inside a closure so it's not chaining. It's possible it's just working now because everything is fast loading on my dev box but just enough slower with Deferred's having to resolve.

I'm going back to review what's happening in my app. If I find that the problem is in my code, I'll request this ticket be closed, otherwise I'll report my findings.

Thanks, Ken

comment:6 Changed 8 years ago by bill

There's nothing magic about Deferreds. It sounds like you have code that needs to run inside the callback, but you are executing it outside the callback.

comment:7 in reply to:  6 Changed 8 years ago by kbenjamin

Bill, you are, naturally, correct.

The problem was with my code, related to recursive require() calls with prior require()'s as a dependency. There were some other related issues in my code, all of which were masked by the extra time wrapping require inside a Deferred caused. It probably wouldn't have shown up until it was deployed in production so I'm glad it's fixed now.

Please close this ticket.

Replying to bill:

There's nothing magic about Deferreds. It sounds like you have code that needs to run inside the callback, but you are executing it outside the callback.

comment:8 Changed 8 years ago by bill

Resolution: invalid
Status: newclosed

OK, glad it's working for you. I'll close this then.

Note: See TracTickets for help on using tickets.