If you’re following along with my UI Component and uiElement Internals series, you know about Magento’s uiRegistry
module. You can use this module to fetch the scoped Knockout.js view models by registered name
requirejs(['uiRegistry'], function(reg){
console.log(
reg.get('customer')
);
});
or by using a callback function to see every registered view model.
requirejs(['uiRegistry'], function(reg){
reg.get(function(item){
console.log(item);
});
});
While useful as a debugging tool, using the uiRegistry
with real Magento modules presents a problem – you can never be certain when a module is available due to RequireJS’s asynchronous module loading. While asynchronous loading is great for performance, and for developers able to work within their own self contained non-global state – on the ground web developers often need access to data that’s only accessible via a registered view model.
The problem is, there’s no way to guarantee that
reg.get('customer')
will always return a the registered customer
view model. Depending on network latency, its possible your own RequireJS module may run before the customer
view model is available.
Fortunately, the uiRegistry
’s get
method features its own asynchronous loading features. Consider the following program
requirejs(['uiRegistry'], function(reg){
console.log("Starting the Program");
console.log("Requesting the item with the registry index of our_registered_item");
reg.get('our_registered_item', function(item){
console.log("We Just Called the Callback");
console.log(item);
});
console.log("Adding The Item");
var object = {foo:"bar"}
reg.set('our_registered_item', object);
});
Run the above program in your javascript console, and you’ll see the following output
Starting the Program
Requesting the item with the registry index of our_registered_item
Adding The Item
We Just Called the Callback
Object {foo: "bar"}
By using the get
method with a callback
reg.get('our_registered_item', function(item){
console.log("We Just Called the Callback");
console.log(item);
});
We told the uiRegistry
Hey, once the
our_registered_item
object is available, run our function.
Since our_registered_item
wasn’t available immediately, our program kept running. The callback didn’t fire until our_registered_item
was actually registered.
If you need more than a single item, this asynrcoutous functionality works with multiple references. Consider the following
requirejs(['uiRegistry'], function(reg){
console.log("Starting the Program");
console.log("Requesting the item with the registry index of our_registered_item");
reg.get(['our_registered_item_1','our_registered_item_2'], function(item1, item2){
console.log("We Just Called the Callback");
console.log(item1);
console.log(item2);
});
console.log("Adding The Item");
var object = {foo:"bar"}
reg.set('our_registered_item_1', object);
var object = {baz:"ban"}
reg.set('our_registered_item_2', object);
});
Here we passed get
an array of registry keys
reg.get(['our_registered_item_1','our_registered_item_2'], function(item1, item2){
console.log("We Just Called the Callback");
console.log(item1);
console.log(item2);
});
Again, our callback was not called until both our_registered_item_1
and our_registered_item_2
were available in the registry.
If you’re using the uiRegistry
in your own program, you must use this sort of pattern for fetching items. While the code may work in your development enviornment without it, network latency from the production servers means you can never be sure when an item is available. RequireJS module that use the uiRegistry
should all look something like this
requirejs(['uiRegistry'], function(reg){
/* ... */
reg.get([/* list of registry entries */], function(item1, item2, etc.){
//program logic here
});
/* ... */
});