JavaScript: Bridge Mode in Design Mode

Source: Internet
Author: User

JavaScript: Bridge Mode in Design Mode
Introduction

Bridge separates abstract parts from their implementations so that they can all change independently.

Body

The bridge mode is most commonly used in event monitoring. first look at the Code:

addEvent(element, 'click', getBeerById);function getBeerById(e) {var id = this.id;asyncRequest('GET', 'beer.uri?id=' + id, function(resp) {// Callback response.console.log('Requested Beer: ' + resp.responseText);});}

The above code has a problem that getBeerById must have a browser context to use, because it uses the this. id attribute internally. If the context is not used, stop. So generally, a slightly experienced programmer will transform the program into the following form:

Function getBeerById (id, callback) {// send the request by ID, and then return the data asyncRequest ('get', 'beer. uri? Id = '+ id, function (resp) {// callback responsecallback (resp. responseText );});}

More practical, right? First, the ID can be passed in at will, and a callback function is provided for user-defined processing functions. But what does this have to do with the bridge? This is what the code below will reflect:

addEvent(element, 'click', getBeerByIdBridge);  function getBeerByIdBridge (e) {    getBeerById(this.id, function(beer) {      console.log('Requested Beer: '+beer);  });}

Here, getBeerByIdBridge is the bridge we have defined. It is used to connect abstract click events with getBeerById. It also connects the ID of the event source and the custom call function (console. log output) is passed into the getBeerById function as a parameter.

This example looks a little simple. Let's look at a complex example.

XHR connection queue

We need to build a queue that stores a lot of ajax requests. The queue is mainly used to ensure that the first added request is processed first. At any time, we can suspend requests, delete requests, retry requests, and support subscription events for each request.

Basic Core functions

Before the official start, we should first define the core encapsulation functions. The first is the function encapsulation of asynchronous requests:
 

var asyncRequest = (function () {    function handleReadyState(o, callback) {        var poll = window.setInterval(                    function () {                        if (o && o.readyState == 4) {                            window.clearInterval(poll);                            if (callback) {                                callback(o);                            }                        }                    },                    50                    );    }    var getXHR = function () {        var http;        try {            http = new XMLHttpRequest;            getXHR = function () {                return new XMLHttpRequest;            };        }        catch (e) {            var msxml = [                        'MSXML2.XMLHTTP.3.0',                        'MSXML2.XMLHTTP',                        'Microsoft.XMLHTTP'                        ];            for (var i = 0, len = msxml.length; i < len; ++i) {                try {                    http = new ActiveXObject(msxml[i]);                    getXHR = function () {                        return new ActiveXObject(msxml[i]);                    };                    break;                }                catch (e) { }            }        }        return http;    };    return function (method, uri, callback, postData) {        var http = getXHR();        http.open(method, uri, true);        handleReadyState(http, callback);        http.send(postData || null);        return http;    };})();

The self-executed function encapsulated above is a common Ajax request function, which can be understood by anyone who wants to attribute Ajax.

Next we will define a general method for adding a method (function:

Function.prototype.method = function (name, fn) {    this.prototype[name] = fn;    return this;};

Finally, add two methods about the array, one for traversing and the other for filtering:

if (!Array.prototype.forEach) {    Array.method('forEach', function (fn, thisObj) {        var scope = thisObj || window;        for (var i = 0, len = this.length; i < len; ++i) {            fn.call(scope, this[i], i, this);        }    });}if (!Array.prototype.filter) {    Array.method('filter', function (fn, thisObj) {        var scope = thisObj || window;        var a = [];        for (var i = 0, len = this.length; i < len; ++i) {            if (!fn.call(scope, this[i], i, this)) {                continue;            }            a.push(this[i]);        }        return a;    });}

Because some new browsers already support these two functions (or some class libraries already support them), you must first determine that if they are already supported, they will not be processed.

Observer System

The observer plays an important role in the event process in the queue. It can subscribe to the event when the queue is processed (successful, failed, suspended:

window.DED = window.DED || {};DED.util = DED.util || {};DED.util.Observer = function () {    this.fns = [];}DED.util.Observer.prototype = {    subscribe: function (fn) {        this.fns.push(fn);    },    unsubscribe: function (fn) {        this.fns = this.fns.filter(            function (el) {                if (el !== fn) {                    return el;                }            }            );            },    fire: function (o) {        this.fns.forEach(            function (el) {                el(o);            }            );    }};
Main queue implementation code

First, subscribe to the main attributes and event delegation of the queue:
 

DED. queue = function () {// Queue containing the request. this. queue = []; // use the Observable object in three different states so that you can subscribe to the event this at any time. onComplete = new DED. util. observer; this. onFailure = new DED. util. observer; this. onFlush = new DED. util. observer; // core attribute, which can be set during external calls. retryCount = 3; this. currentRetry = 0; this. paused = false; this. time out = 5000; this. conn = {}; this. timer = {};};

Then, use the chain call of DED. Queue. method to add many available methods to the Queue:
 

DED. Queue. method ('flush ', function () {// flush method if (! This. queue. length> 0) {return;} if (this. paused) {this. paused = false; return;} var that = this; this. currentRetry ++; var abort = function () {that. conn. abort (); if (that. currentRetry = that. retryCount) {that. onFailure. fire (); that. currentRetry = 0;} else {that. flush () ;}; this. timer = window. setTimeout (abort, this. timeout); var callback = function (o) {window. clearTimeout (that. timer); that. currentRetry = 0; that. queue. shift (); that. onFlush. fire (o. responseText); if (that. queue. length = 0) {that. onComplete. fire (); return;} // recursive call to flush that. flush () ;}; this. conn = asyncRequest (this. queue [0] ['method'], this. queue [0] ['uri '], callback, this. queue [0] ['params']);}). method ('setretrycount', function (count) {this. retryCount = count ;}). method ('settimeout', function (time) {this. timeout = time ;}). method ('add', function (o) {this. queue. push (o );}). method ('pause', function () {this. paused = true ;}). method ('dequeue ', function () {this. queue. pop ();}). method ('clear', function () {this. queue = [];});

The code looks a lot. After the code is folded, we can find that the flush, setRetryCount, setTimeout, add, pause, dequeue, and clear methods are defined on the queue.

Simple call
Var q = new DED. queue; // set a higher number of retries to cope with slow connections. setRetryCount (5); // set the timeout time q. setTimeout (1000); // Add two requests. q. add ({method: 'get', uri: '/path/to/file. php? Ajax = true '}); q. add ({method: 'get', uri:'/path/to/file. php? Ajax = true & woe = me '}); // flush queue q. flush (); // pause the queue and save the remaining q. pause (); // clear. q. clear (); // Add two requests. q. add ({method: 'get', uri: '/path/to/file. php? Ajax = true '}); q. add ({method: 'get', uri:'/path/to/file. php? Ajax = true & woe = me '}); // Delete the last request from the queue. q. dequeue (); // Flushq. flush () again ();
What about bridging?

There is no bridge in the above call code. What about the bridge? Looking at the complete example below, we can see that there are bridges everywhere:

  <Script src = utils. js> </script> <script src = queue. js> </script> <script type = text/javascript> addEvent (window, 'load', function () {// implementation. var q = new DED. queue; q. setRetryCount (5); q. setTimeout (3000); var items = $ ('items '); var results = $ ('result'); var queue = $ ('queue-items '); // save your tracing request var requests = [] on the client; // subscribe to the special processing step q after each request is flushed. onFlush. subscribe (function (data) {results. innerHTML = dat A; requests. shift (); queue. innerHTML = requests. toString () ;}); // subscription time processing step q. onFailure. subscribe (function () {results. innerHTML + = 'Connection Error! ';}); // Processing steps for successful subscription x q. onComplete. subscribe (function () {results. innerHTML + = 'completed! ';}); Var actionDispatcher = function (element) {switch (element) {case 'flush': q. flush (); break; case 'dequeue ': q. dequeue (); requests. pop (); queue. innerHTML = requests. toString (); break; case 'pause': q. pause (); break; case 'clear': q. clear (); requests = []; queue. innerHTML = ''; break ;}}; var addRequest = function (request) {var data = request. split ('-') [1]; q. add ({method: 'get', uri: 'B Ridge-connection-queue.php? Ajax = true & s = '+ data, params: null}); requests. push (data); queue. innerHTML = requests. toString () ;}; addEvent (items, 'click', function (e) {var e = e | window. event; var src = e.tar get | e. srcElement; try {e. preventDefault ();} catch (ex) {e. returnValue = false;} actionDispatcher (src. id) ;}); var adders =$ ('adders'); addEvent (adders, 'click', function (e) {var e = e | window. event; var src = e.tar get | e. srcElement; try {e. preventDefault ();} catch (ex) {e. returnValue = false;} addRequest (src. id) ;}); </script> An asynchronous connection request adds a new request to the queue 
  • Add 01 to queue
  • Add 02 to queue
  • Add 03 to queue
Queue control
  • Flush
  • Dequeue
  • Pause
  • Clear
Result:

In this example, you can perform various operations, such as flush queue, suspend queue, delete requests in the queue, and clear the queue. At the same time, I believe you have realized the power of bridging.

Summary

The advantages of the bridge mode are also obvious. We only list the main advantages:

  1. When separating interfaces and implementations, an implementation may not always be bound to an interface. The implementation of abstract classes (functions) can be configured at runtime, an object can even change its implementation at runtime. It fully decouples the abstraction and implementation, and is also conducive to layering to produce a better structured system.
  2. Improve scalability
  3. The implementation details are transparent to the customer, and the Implementation Details can be hidden from the customer.

    At the same time, the Bridge Mode also has its own shortcomings:

    A large number of classes will increase development costs and may also reduce performance.

     

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.