简体   繁体   中英

Javascript method proxy and AngularJS

I am using AngularJS and while accessing the same method based variable ie {{someValue()}} , I realised the method is called every times the scope is refreshed through an $apply. As my method is deterministic ie only depends on few inputs I know, how could I make a proxy to avoid processing the same data many times ?

[UPDATE] I recently discovered the memoize (understore and lodash) function which acts as in similar fashion: https://lodash.com/docs#memoize

Here below my previous answer:

I solved the problem building a MethodProxy object

  1. The MethodProxy takes the callback as an argument (the method to proxy)

  2. We call the method through the proxy, if the arguments are strictly the same, the proxy will return the cached result, otherwise it will update its value using the callback, store and return the result.

NOTE: the following solution compares the arguments using _.isEqual which takes part of UnderscoreJS or Lodash if you need a slow (approximatively 3 times slower ) but temporary comparator just define

_ = {isEqual:function(a,b){return JSON.stringify(a)===JSON.stringify(b)}};

But again, I strongly recommend using Lodash which is optimised, here is the MethodProxy:

function MethodProxy(callback_)
{
    var lastArguments = undefined;
    var callback = callback_;
    var cachedAnswer = undefined;
    this.call = function()
    {
        if (_.isEqual(lastArguments, arguments))
        {
            return cachedAnswer;
        }
        else
        {
            lastArguments = arguments;
            cachedAnswer = callback.apply(this, arguments);
            return cachedAnswer;
        }
    };
}

Example usage:

var test = new MethodProxy(function(value)
{
console.log("The method is called");
return value;
})

test.call("hello");// prints "The method is called" then return "hello"
test.call("hello");// returns "hello" (the cached value)
test.call("world");// prints "The method is called" then return "world"

How to use it within angular ?

in JS:

function myDataProxy = new MethodProxy(function(arg1, arg2)
{
// your expensive CPU method
return arg1+arg2;
})

$scope.myData = function()
{
var value1 = $scope.valueWhichCanChangeOrNot;
var value2 = $scope.anotherValueWhichCouldHaveBeenUpdated;
return myDataProxy.call(value1, value2);
}

in HTML:

{{myData()}}

Limitations: The method must be deterministic ie should always give the same output given its input arguments If the arguments are huge it might take some times to compare them.

Other: You can capture values from the function itself, only the relevant parameters to check if they changed needs to be sent to the call method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM