Learn the proxy pattern for JavaScript design patterns

  • 2020-11-30 08:06:00
  • OfStack

Stars have agents to act as agents. If ask a star to do 1 commercial performance, can contact its agent only, the agent can talk about the details of commercial performance and remuneration well, give the contract to the star to sign again.

Definition 1.

Proxy pattern: Provides a substitute or placeholder for an object to control access to it.
Agents are divided into protected agents and virtual agents
Secure proxy: Used to control access to target objects by objects with different permissions, it is difficult to determine who has access to an object in JavaScript, so the secure proxy is difficult to implement.

2. Image pre-loading (the most common virtual agent application scenario)

Image pre-loading is a common technique. If the src attribute is directly set to an img tag node, the position of the image will be blank for some time due to the image size or poor network. The common practice is to use one loading image to hold the space beforehand, then asynchronously load the image, and fill it into the img node after the image is loaded.
Implementation principle:
Create 1 Image object: var a = new Image();
src: a. src = "xxx. gif"; src: a. src = "xxx. gif";
This is equivalent to caching 1 image for the browser.

The complete attribute of the Image object can be used to detect whether the image has been loaded. Each Image object has an complete attribute. When the image is in the loading process, the attribute value is false. When any event of onload, onerror, onabort occurs, the image loading process is over, and the complete attribute is true.

(1) Non-proxy implementation


var myImage = (function() {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);
  var img = new Image();

  img.onload = function() {
    imgNode.src = img.src;
  };

  return {
    setSrc: function(src) {
      imgNode.src = "./images/loading.gif";
      img.src = src;
    }
  }
})();

myImage.setSrc("./images/originImg.png");

(2) Agent implementation


//  Create a picture DOM
var myImage = (function() {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);

  return {
    setSrc: function(src) {
      imgNode.src = src;
    }
  };
})();

//  The agent 
var proxyImage = (function() {
  var img = new Image();

  img.onload = function() {
    myImage.setSrc(this.src);  // this Point to the img ! img After loading is complete, will img.src Passed to the myImage
  };

  return {
    setSrc: function(src) {
      myImage.setSrc("./images/loading.gif");   // loading
      img.src = src;
    }
  };
})();

proxyImage.setSrc("./images/originImg.png");

The benefits of using the proxy pattern: make each function function single 1, implementing the "single responsibility principle" of object design!

3. File synchronization

Suppose we are doing a file synchronization function, when checkbox is selected, its corresponding file will be synchronized to another server.


<body>
    <input type="checkbox" id="1" /> file 1
    <input type="checkbox" id="2" /> file 2
    <input type="checkbox" id="3" /> file 3
    <input type="checkbox" id="4" /> file 4
    <input type="checkbox" id="5" /> file 5
    <input type="checkbox" id="6" /> file 6
  </body>

It is obviously not reasonable to synchronize 1 time without selecting 1 checkbox. Because the biggest overhead in web development is network requests.
Solution: Collect requests over a period of time through a proxy function and send them to the server once.


var synchronousFile = function(id) {
  console.log(" Start synchronizing files, id To: " + id);
};

var proxySynchonousFile = (function() {
  var cache = [],   //  Save the files that need to be synchronized this time id
    timer;     //  The timer 

  return function(id) {
    cache.push(id);
    if(timer) { 
      //  Do not overwrite a timer that has been started 
      return;
    }

    timer = setTimeout(function(){
      synchronousFile(cache.join(","));
      clearTimeout(timer);
      timer = null;
      cache.length = 0;  //  Clear the cache 
    }, 2000);
  }
})();

var checkboxs = document.getElementsByTagName("input");

for(var i = 0, c; c = checkboxs[i]; i++) {
  c.onclick = function() {
    if(this.checked === true) {
      proxySynchonousFile(this.id);
    }
  }
}

4. Cache agent - Multiplication (sequence 1 template 1 sample)


var mult = function() {
  var result = 1;
  for(var i = 0, l = arguments.length; i < l; i++) {
    result= result * arguments[i];
  }
  return result;
};

var proxyMult = (function() {
  var cache = {};   // {"1,2,3": 6}
  return function() {
    var args = Array.prototype.join.call(arguments, ",");
    if(args in cache) {
      return cache[args];
    }
    return cache[args] = mult.apply(this, arguments);
  }
})();

console.log(proxyMult(1, 2, 3));

//  Modification: 

var proxyFactory = function(fn) {
  var cache = {};
  return function() {
    var args = Array.prototype.join.call(arguments, ",");
    if(args in cache) {
      return cache[args];
    }
    return cache[args] = fn.apply(this, arguments);
  }  
};

console.log(proxyFactory(mult)(1, 2, 3));

I hope this article has been helpful in learning javascript programming.


Related articles: