Make a JavaScript getter act both as getter and as a function
So I have a object that exposes a getter to retrieve data after some expensive synchronous computation.
function processData() { // lots of stuff happening here return result; } return { get data () { // some checks happening here return procesData(); } } |
var obj = new MyObject(); var x = obj.data; // this stops things for 2 or 3 seconds // .. carry on |
Since this is part of an already used library, is getting pretty hard to change the public interface for backwards compatibility reasons.
The thing is I've added a asynchronous processData method and i want to make that available as well without changing the public methods. The normal thing to do would be to convert the getter into a method called getData() and
getDataAsync(callback)
but that wouldn't work because it will annoy some people when they see their code isn't working anymore.
The solution couldn't be easier but it took me a while to figure it out and as always, it's sharing time.
function processData() { // lots of stuff happening here return result; } function processDataAsync(callback) { if (!arguments.length || arguments.length && typeof arguments[0] !== "function") { return processData(); } // lots of stuff happening here but asynchronously callback(result); } processDataAsync.__proto__ = {valueOf : processData}; return { get data () { // some checks happening here return processDataAsync; } } |
var obj = new MyObject(); var x = obj.data; // get data synchronously // .. carry on after 2 seconds var obj = new MyObject(); var x = obj.data(); // still a synchronous call since no callback was given // .. carry on after 2 seconds var obj = new MyObject(); obj.data(function(result) { // get the data here after few seconds without blocking anything } // .. carry on right away |
So now the same getter can be used from now on as a asynchronous function if used with parentheses and given a callback or as a simple getter.