We’ve recently added two new API’s on XPCOMUtils that make a common coding pattern simpler to do. It is quite common to have “smart getters” to store a reference to a service that you use in JavaScript. Normally, folks write code that looks something like this:
this.__defineGetter__("_ioService", function() {
delete this._ioService;
return this._ioService = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
});
That gets long and verbose if you have any more than a few of these getters. The new approach looks like this:
XPCOMUtils.defineLazyServiceGetter(this, "_ioService",
"@mozilla.org/network/io-service;1",
"nsIIOService");
The net result is a lot less boilerplate code, which, in my opinion, is a lot nicer to read. I’ve already converted the toolkit code in the Places module over, and the resulting code is much nicer.
Sometimes, however, you want to have a getter for something that is not a service. That’s where the second API comes in. You can pass in a lambda function that will be called when the value is needed for the first time. From then on, the value is cached. Some old code may look something like this:
this.__defineGetter__("_db", function() {
delete this._db;
return this._db = Components.classes["@mozilla.org/browser/nav-history-service;1"].
getService(Components.interfaces.nsPIPlacesDatabase).
DBConnection;
});
With the new API, that code turns into this:
XPCOMUtils.defineLazyGetter(this, "_db", function() {
return Components.classes["@mozilla.org/browser/nav-history-service;1"].
getService(Components.interfaces.nsPIPlacesDatabase).
DBConnection;
});
Again, much nicer looking! If you are interested, the implementation of these methods can be found here.