einführen
Der Brückenmodus trennt abstrakte Teile von seinen Implementierungsteilen, damit alle unabhängig variiert werden können.
Text
Der Brückenmodus wird am häufigsten bei der Ereignisüberwachung verwendet. Schauen wir uns zuerst einen Code an:
Die Codekopie lautet wie folgt:
AddEvent (Element, 'Click', getBeerbyId);
Funktion getBeerbyId (e) {
var id = this.id;
Asyncrequest ('get', 'Beer.uri? id =' + id, function (resp) {
// Rückrufantwort.
console.log ('angefordertes Bier:' + resp.responsetext);
});
}
Es gibt ein Problem mit dem obigen Code, dass GetBeerbyId einen Browser -Kontext verwenden muss, da er diese ID -Eigenschaft intern verwendet. Wenn der Kontext nicht verwendet wird, wird er ein Stopp sein. Im Allgemeinen verwandelt ein wenig erfahrener Programmierer das Programm in die folgende Form:
Die Codekopie lautet wie folgt:
Funktion getBeerbyId (ID, Callback) {
// die Anfrage per ID senden und die Daten zurückgeben
Asyncrequest ('get', 'Beer.uri? id =' + id, function (resp) {
// Rückrufantwort
Rückruf (resp. responsetext);
});
}
Praktischer, oder? Zunächst kann die ID nach Belieben übergeben werden, und es wird auch eine Rückruffunktion für benutzerdefinierte Verarbeitungsfunktionen bereitgestellt. Aber was hat das mit Überbrückung zu tun? Dies wird der folgende Code widerspiegeln:
Die Codekopie lautet wie folgt:
AddEvent (Element, 'Click', getBeerbyIdbridge);
Funktion getBeerbyidbridge (e) {
GetBeerbyId (this.id, function (Bier) {
console.log ('angefordertes Bier:'+Beer);
});
}
Hier ist GetBeerbyIdbridge die Brücke, die wir definieren, mit der das abstrakte Klickereignis und GetBeerbyID verbunden und gleichzeitig die ID der Ereignisquelle und die benutzerdefinierte Anruffunktion (Konsole.log -Auslöser) in die GetBeerbyid -Funktion als Parameter übergeben wird.
Dieses Beispiel sieht ein bisschen einfach aus. Nehmen wir ein weiteres komplizierteres praktisches Beispiel.
Tatsächliche XHR -Verbindungswarteschlange
Wir möchten eine Warteschlange erstellen, in der viele Ajax -Anfragen in der Warteschlange gespeichert sind. Die Verwendung von Warteschlangen liegt hauptsächlich daran, dass wir sicherstellen müssen, dass die angeschlossenen Anfragen zuerst verarbeitet werden. Wir können jederzeit Anfragen pausieren, Anfragen löschen, Anfragen wiederholen und Abonnementereignisse für jede Anfrage unterstützen.
Grundlegende Kernfunktionen
Definieren wir vor dem offiziellen Start mehrere Kernkapselungsfunktionen. Erstens ist die erste Funktionskapselung asynchroner Anfragen:
Die Codekopie lautet wie folgt:
var asyncrequest = (function () {
Funktion HandlereadyState (O, Callback) {
var Poll = Fenster.SetInterval (
function () {
if (o && o.readystate == 4) {
Fenster.ClearInterval (Umfrage);
if (rallback) {
Rückruf (o);
}
}
},
50
);
}
var getXhr = function () {
var http;
versuchen {
http = new xmlhttprequest;
getXhr = function () {
Rückgabe neuer xmlhttprequest;
};
}
fangen (e) {
var msxml = [
'Msxml2.xmlhttp.3.0',
'Msxml2.xmlhttp',
'Microsoft.xmlhttp'
];
für (var i = 0, len = msxml.length; i <len; ++ i) {
versuchen {
http = new ActiveXObject (msxml [i]);
getXhr = function () {
Neue ActiveXObject zurückgeben (MSXML [i]);
};
brechen;
}
fangen (e) {}
}
}
Rückgabe http;
};
Rückgabefunktion (Methode, URI, Rückruf, Postdata) {
var http = getXhr ();
http.open (Methode, Uri, wahr);
HandlereadyState (HTTP, Callback);
http.send (postdata || null);
Rückgabe http;
};
}) ();
Die eingekapselte Self-Executing-Funktion ist eine allgemeine AJAX-Anforderungsfunktion, und ich glaube, dass jeder mit dem Attribut AJAX sie verstehen kann.
Als nächstes definieren wir eine allgemeine Methode zum Hinzufügen von Methoden (Funktionen):
Die Codekopie lautet wie folgt:
Function.prototype.method = Funktion (Name, fn) {
this.prototype [name] = fn;
gib dies zurück;
};
Fügen Sie schließlich 2 Methoden zu Arrays hinzu, eine für die Traversal und eine zum Filtern:
Die Codekopie lautet wie folgt:
if (! array.prototype.foreach) {
Array.Method ('foreach', Funktion (fn, thisobj) {
var scope = thisobj || Fenster;
für (var i = 0, len = this.Length; i <len; ++ i) {
fn.call (Scope, this [i], i, this);
}
});
}
if (! array.prototype.filter) {
Array.Method ('Filter', Funktion (fn, thisobj) {
var scope = thisobj || Fenster;
var a = [];
für (var i = 0, len = this.Length; i <len; ++ i) {
if (! fn.call (scope, this [i], i, this) {
weitermachen;
}
a.push (this [i]);
}
Rückkehr a;
});
}
Da einige neue Browser diese beiden Funktionen bereits unterstützen (oder einige Klassenbibliotheken bereits unterstützen), müssen wir zuerst beurteilen, ob sie bereits unterstützt werden, und wenn sie bereits unterstützt werden, werden sie nicht mehr verarbeitet.
Beobachtersystem
Beobachter spielen eine wichtige Rolle im Ereignisverfahren in der Warteschlange und können Ereignisse in der Warteschlange abonnieren (Erfolg, Misserfolg, ausstehend):
Die Codekopie lautet wie folgt:
window.ded = window.ded || {};
Ded.util = ded.util || {};
Ded.util.observer = function () {
this.fns = [];
}
Ded.util.observer.prototype = {{
Abonnieren: Funktion (fn) {
this.fns.push (fn);
},
Abbestellen: Funktion (fn) {
this.fns = this.fns.filter (
Funktion (el) {
if (el! == fn) {
return el;
}
}
);
},
Feuer: Funktion (o) {
this.fns.foreach (
Funktion (el) {
el (o);
}
);
}
};
Der Hauptimplementierungscode der Warteschlange
Zunächst abonnieren Sie die Hauptattribute und Event -Delegierten der Warteschlange:
Die Codekopie lautet wie folgt:
Ded.queue = function () {
// enthält die Warteschlange für Anfragen.
this.queue = [];
// Verwenden Sie beobachtbares Objekt in 3 verschiedenen Zuständen, damit Sie Ereignisse jederzeit abonnieren können
this.oncomplete = new Ded.util.observer;
this.onfailure = new Ded.util.observer;
this.onflush = new Ded.util.observer;
// Kerneigenschaften können während externer Anrufe festgelegt werden
this.retrycount = 3;
this.currentratry = 0;
this.pauded = false;
that timeout = 5000;
this.conn = {};
this.timer = {};
};
Dann werden durch den angeketteten Anruf von Ded.queue.method viele verfügbare Methoden zur Warteschlange hinzugefügt:
Die Codekopie lautet wie folgt:
Ded.queue.
Methode ('Flush', function () {
// Flush -Methode
if (! this.queue.length> 0) {
zurückkehren;
}
if (this.pauded) {
this.pauded = false;
zurückkehren;
}
var das = dies;
this.currentratry ++;
var abort = function () {
that.conn.abort ();
if (that.currentratry == that.retryCount) {
that.onfailure.fire ();
that.currentratry = 0;
} anders {
that.flush ();
}
};
this.timer = window.settimeout (abort, this.timeout);
var callback = function (o) {
window.clearTimeout (this.timer);
that.currentratry = 0;
that.queue.shift ();
that.onflush.fire (o.responsetext);
if (that.queue.length == 0) {
that.oncomplete.fire ();
zurückkehren;
}
// rekursiver Anruf zum Spülen
that.flush ();
};
this.conn = asyncrequest (
this.queue [0] ['Methode'],
this.queue [0] ['uri'],
Rückruf,
this.queue [0] ['Params']
);
}).
method ('setRetryCount', function (count) {
this.retryCount = count;
}).
Methode ('setTimeout', Funktion (Zeit) {
that timeout = Zeit;
}).
method ('add', function (o) {
this.queue.push (o);
}).
method ('pause', function () {
this.paused = true;
}).
Methode ('dequeue', function () {
this.queue.pop ();
}).
Methode ('Clear', function () {
this.queue = [];
});
Der Code sieht viel aus, und nach der Faltung können Sie feststellen, dass er tatsächlich in der Warteschlange mit Flush, SetReRyCount, SetTimeout, Hinzufügen, Pause, Dequeue und klaren Methoden definiert ist.
Einfacher Anruf
Die Codekopie lautet wie folgt:
var q = new ded.queue;
// Stellen Sie die Anzahl der Wiederholungen ein wenig höher, um mit langsamen Verbindungen fertig zu werden
Q.SetRetryCount (5);
// Zeitüberschreitungszeit festlegen
Q.Settimeout (1000);
// 2 Anfragen hinzufügen.
Q.Add ({{
Methode: 'Get',
URI: '/path/to/file.php?ajax=true' '
});
Q.Add ({{
Methode: 'Get',
URI: '/path/to/file.php?ajax=true&woe=me'
});
// Flush -Warteschlange
q.flush ();
// Machen Sie die Warteschlange an und speichern Sie die verbleibenden
Q.Pause ();
// Klar.
q.clear ();
// 2 Anfragen hinzufügen.
Q.Add ({{
Methode: 'Get',
URI: '/path/to/file.php?ajax=true' '
});
Q.Add ({{
Methode: 'Get',
URI: '/path/to/file.php?ajax=true&woe=me'
});
// die letzte Anfrage aus der Warteschlange löschen.
q.dequeue ();
// wieder spülen
q.flush ();
Wo ist die Brücke?
Der oben genannte Anrufcode gibt es keine Brücke. Was ist also mit der Brücke? Schauen Sie sich das vollständige Beispiel unten an und Sie werden feststellen, dass überall Brücken vorhanden sind:
Die Codekopie lautet wie folgt:
<! DocType html public "-// w3c // dtd html 4.01 // en"
"http://www.w3.org/tr/html4/strict.dtd">
<html>
<kopf>
<meta http-äquiv = "content-type" content = "text/html; charset = utf-8">
<title> Ajax Connection Queue </title>
<script src = "utils.js"> </script>
<script src = "queue.js"> </script>
<script type = "text/javaScript">
AddEvent (Fenster, "Laden", function () {
// erreichen.
var q = new ded.queue;
Q.SetRetryCount (5);
Q.Settimeout (3000);
var items = $ ('items');
var resultes = $ ('Ergebnisse');
var queue = $ ('Queue-items');
// Speichern Sie Ihre Anfrage im Kunden
var requests = [];
// Abonnieren Sie nach jeder Anfrage nach Flush spezielle Verarbeitungsschritte
q.onflush.subscribe (Funktion (Daten) {
results.innerhtml = Daten;
Requests.Shift ();
queue.innerhtml = requests.toString ();
});
// Abonnementzeitsverarbeitungsschritte
q.onfailure.subscribe (function () {
results.innerhtml += '<span style = "color: rot;"> Verbindungsfehler! </span>';
});
// Abonnieren Sie alle erfolgreichen Verarbeitungsschritte x
q.oncomplete.subScribe (function () {
results.innerhtml += '<span style = "color: grün;"> abgeschlossen! </span>';
});
var ActionDispatcher = Funktion (Element) {
Switch (Element) {
Fall 'Flush':
q.flush ();
brechen;
Fall 'Dequeue':
q.dequeue ();
Anfragen.Pop ();
queue.innerhtml = requests.toString ();
brechen;
Fall 'Pause':
Q.Pause ();
brechen;
Fall 'klar':
q.clear ();
Anfragen = [];
queue.innerhtml = '';
brechen;
}
};
var addRequest = function (request) {
var data = request.split ('-') [1];
Q.Add ({{
Methode: 'Get',
URI: 'Bridge-Connection-Queue.php? Ajax = True & S =' + Daten,
Parameter: NULL
});
Requests.push (Daten);
queue.innerhtml = requests.toString ();
};
AddEvent (Elemente, 'Click', Funktion (e) {
var e = e || Fenster.Event;
var src = e.target || e.srcelement;
versuchen {
E.PreventDefault ();
}
fangen (ex) {
E. returnValue = false;
}
ActionDispatcher (src.id);
});
var adders = $ ('adders');
AddEvent (Addlers, 'Click', Funktion (e) {
var e = e || Fenster.Event;
var src = e.target || e.srcelement;
versuchen {
E.PreventDefault ();
}
fangen (ex) {
E. returnValue = false;
}
addRequest (src.id);
});
});
</script>
<style type = "text/css" media = "screen">
Körper
{
Schriftart: 100% Georgia, Times, Serif;
}
H1, H2
{
Schriftgewicht: normal;
}
#Queue-Items
{
Höhe: 1,5EM;
}
#Add-Stuff
{
Polsterung: .5em;
Hintergrund: #ddd;
Grenze: 1PX Solid #bbb;
}
#Ergebnisse
{
Polsterung: .5em;
Grenze: 1PX Solid #bbb;
}
</style>
</head>
<body id = "Beispiel">
<div id = "doc">
<h1>
Asynchronous Join -Anfrage </h1>
<div id = "Queue-items">
</div>
<div id = "add-Stuff">
<h2> Fügen Sie der Warteschlange </H2> eine neue Anfrage hinzu
<ul id = "Addlers">
<li> <a href = "#" id = "action-01"> hinzufügen "01" zur Warteschlange </a> </li>
<li> <a href = "#" id = "action-02"> hinzufügen "02" zur Warteschlange </a> </li>
<li> <a href = "#" id = "action-03"> hinzufügen "03" zur Warteschlange </a> </li>
</ul>
</div>
<h2> Angebotskontrolle </h2>
<ul id = 'items'>
<li> <a href = "#" id = "Flush"> Flush </a> </li>
<li> <a href = "#" id = "dequeue"> dequeue </a> </li>
<li> <a href = "#" id = "pause"> pause </a> </li>
<li> <a href = "#" id = "Clear"> Clear Clear </a> </li>
</ul>
<div id = "Ergebnisbereich">
<h2>
Ergebnis:
</h2>
<div id = "Ergebnisse">
</div>
</div>
</div>
</body>
</html>
In diesem Beispiel können Sie verschiedene Aktionen wie Flush -Warteschlangen, Pause Warteschlangen, Löschen von Anforderungen in Warteschlangen, klare Warteschlangen usw. ausführen. Gleichzeitig glaube ich, dass jeder auch die Kraft der Brücken erlebt hat.
Zusammenfassen
Die Vorteile des Brückenmodus sind ebenfalls offensichtlich. Wir werden nur ein paar Hauptvorteile auflisten:
1. Trennen Sie die Schnittstellen- und Implementierungsteile. Eine Implementierung ist möglicherweise nicht an eine Schnittstelle gebunden. Die Implementierung der abstrakten Klasse (Funktion) kann zur Laufzeit konfiguriert werden, und ein Objekt kann sogar seine Implementierung zur Laufzeit ändern. Es entkoppelt auch die Abstraktion und Implementierung vollständig, was auch für die Schichtung förderlich ist und so ein besseres strukturiertes System erzeugt.
2. Die Skalierbarkeit verbessern
3. Die Implementierungsdetails sind für Kunden transparent und können Implementierungsdetails von Kunden ausblenden.
Gleichzeitig hat der Brückenmodus auch seine eigenen Nachteile:
Eine große Anzahl von Klassen wird zu erhöhten Entwicklungskosten führen und können auch die Leistung verringern.