introducir
El modo de puente separa las piezas abstractas de sus piezas de implementación para que todas puedan variar de forma independiente.
texto
El modo puente se usa más comúnmente en el monitoreo de eventos. Veamos primero un código:
La copia del código es la siguiente:
addEvent (elemento, 'hacer clic', getBeerByid);
función getBeerByid (e) {
var id = this.id;
asyncrequest ('get', 'beer.uri? id =' + id, function (resp) {
// Respuesta de devolución de llamada.
console.log ('cerveza solicitada:' + resp.Responsetext);
});
}
Hay un problema con el código anterior que GetBeerByid debe tener un contexto del navegador para ser utilizado, ya que usa esto.id propiedad internamente. Si el contexto no se usa, entonces será una parada. Por lo tanto, generalmente un programador pequeño experimentado transformará el programa en la siguiente forma:
La copia del código es la siguiente:
función getBeerById (id, devolución de llamada) {
// Enviar la solicitud a través de ID y devolver los datos
asyncrequest ('get', 'beer.uri? id =' + id, function (resp) {
// respuesta de devolución de llamada
devolución de llamada (resp.esponsetext);
});
}
Más práctico, ¿verdad? Primero, la ID se puede aprobar a voluntad, y también se proporciona una función de devolución de llamada para las funciones de procesamiento personalizadas. Pero, ¿qué tiene esto que ver con el puente? Esto es lo que reflejará el siguiente código:
La copia del código es la siguiente:
addEvent (elemento, 'hacer clic', getBeerByidbridge);
función getBeerByidbridge (e) {
getBeerByid (this.id, function (cerveza) {
console.log ('cerveza solicitada:'+cerveza);
});
}
Aquí, GetBeerByIdbridge es el puente que definimos, que se utiliza para conectar el evento de clic abstracto y GetBeerByid, y al mismo tiempo pasar la ID de la fuente de eventos y la función de llamada personalizada (console.log salida) a la función getBeerByid como parámetros.
Este ejemplo parece un poco simple, tomemos otro ejemplo práctico más complicado.
Cola real de conexión XHR
Queremos construir una cola, que almacene muchas solicitudes de Ajax en la cola. El uso de colas se debe principalmente a que debemos asegurarnos de que las solicitudes que se unen se procesen primero. En cualquier momento, podemos detener las solicitudes, eliminar solicitudes, volver a intentar las solicitudes y admitir eventos de suscripción para cada solicitud.
Funciones básicas básicas
Antes del inicio oficial, definamos varias funciones de encapsulación básicas. Primero, el primero es la encapsulación de la función de las solicitudes asíncronas:
La copia del código es la siguiente:
var asyncrequest = (function () {
funciones handlereadyState (o, devolución de llamada) {
VAR Poll = Window.SetInterval (
función () {
if (o && o.readyState == 4) {
Window.ClearInterval (encuesta);
if (llamado) {
devolución de llamada (O);
}
}
},
50
);
}
var getxhr = functer () {
var http;
intentar {
http = nuevo xmlhttprequest;
getxhr = function () {
devolver nuevo xmlhttprequest;
};
}
Catch (e) {
var msxml = [
'Msxml2.xmlhttp.3.0',
'Msxml2.xmlhttp',
'Microsoft.xmlhttp'
];
para (var i = 0, len = msxml.length; i <len; ++ i) {
intentar {
http = new ActiveXObject (msxml [i]);
getxhr = function () {
devolver nuevo ActiveXObject (msxml [i]);
};
romper;
}
Catch (e) {}
}
}
devolver http;
};
Función de retorno (método, uri, devolución de llamada, postdata) {
var http = getxhr ();
http.open (método, uri, verdadero);
HandlereadyState (http, devolución de llamada);
http.send (postdata || null);
devolver http;
};
}) ();
La función de auto-ejecutación encapsulada es una función general de solicitud de AJAX, y creo que cualquier persona con el atributo AJAX puede entenderla.
A continuación, definimos un método general para agregar métodos (funciones):
La copia del código es la siguiente:
Function.prototype.method = function (name, fn) {
this.prototype [name] = fn;
devolver esto;
};
Finalmente, agregue 2 métodos sobre matrices, uno para el recorrido y otro para el filtrado:
La copia del código es la siguiente:
if (! Array.prototype.ForEach) {
Array.method ('foreach', function (fn, thisObj) {
Var alcance = thisObj || ventana;
para (var i = 0, len = this.length; i <len; ++ i) {
fn.call (alcance, este [i], i, esto);
}
});
}
if (! Array.prototype.filter) {
Array.method ('filtre', function (fn, thisObj) {
Var alcance = thisObj || ventana;
var a = [];
para (var i = 0, len = this.length; i <len; ++ i) {
if (! fn.call (alcance, este [i], i, esto)) {
continuar;
}
a.push (este [i]);
}
regresar a;
});
}
Debido a que algunos navegadores nuevos ya apoyan estas dos funciones (o algunas bibliotecas de clase ya las apoyan), primero debemos juzgar si ya están compatibles, y si ya están compatibles, ya no serán procesados.
Sistema de observador
Los observadores juegan un papel importante en el proceso de eventos en la cola y pueden suscribirse a los eventos cuando se pone en cola (éxito, fracaso, pendiente):
La copia del código es la siguiente:
window.ded = window.ded || {};
Ded.util = ded.util || {};
Ded.util.observer = function () {
this.fns = [];
}
Ded.util.observer.prototype = {
suscríbete: function (fn) {
this.fns.push (fn);
},
Underscribe: function (fn) {
this.fns = this.fns.filter (
función (el) {
if (el! == fn) {
regresar el;
}
}
);
},
Fuego: función (o) {
this.fns.foreach (
función (el) {
El (O);
}
);
}
};
El principal código de implementación de la cola
Primero, se suscribe a los principales atributos y delegados de eventos de la cola:
La copia del código es la siguiente:
Ded.queue = function () {
// Contiene la cola para solicitudes.
this.queue = [];
// Use el objeto observable en 3 estados diferentes para que pueda suscribirse a los eventos en cualquier momento
this.oncomplete = new Ded.util.observer;
this.onfailure = new Ded.util.observer;
this.onflush = nuevo ded.util.observer;
// Las propiedades del núcleo se pueden configurar durante las llamadas externas
this.rcryCount = 3;
this.CurrentRetry = 0;
this.pacused = false;
this.timeout = 5000;
this.conn = {};
this.timer = {};
};
Luego, a través de la llamada encadenada de Ded.Queue. Método, se agregan muchos métodos disponibles a la cola:
La copia del código es la siguiente:
Ded.Queue.
Método ('Flush', function () {
// método de descarga
if (! this.queue.length> 0) {
devolver;
}
if (this.paused) {
this.pacused = false;
devolver;
}
var que = esto;
this.Currentretry ++;
var abort = function () {
que.conn.abort ();
if (that.currentretry == that.rcryCount) {
que.onfailure.fire ();
que.CurrentRetry = 0;
} demás {
eso.flush ();
}
};
this.timer = window.setTimeout (abort, this.timeout);
VAR Callback = function (o) {
Window.ClearTimeOut (que.timer);
que.CurrentRetry = 0;
que.queue.hift ();
que.onflush.fire (O.Responsetext);
if (that.queue.length == 0) {
que.oncomplete.fire ();
devolver;
}
// Llamada recursiva a FLUSH
eso.flush ();
};
this.conn = asyncrequest (
this.queue [0] ['método'],
this.queue [0] ['uri'],
llamar de vuelta,
this.queue [0] ['params']
);
}).
método ('setcretryCount', function (count) {
this.rcryCount = Count;
}).
Método ('setTimeout', function (time) {
this.timeout = time;
}).
método ('add', function (o) {
this.queue.push (O);
}).
método ('pausa', function () {
this.pacused = verdadero;
}).
método ('dequeue', function () {
this.queue.pop ();
}).
método ('clare', function () {
this.queue = [];
});
El código se ve mucho, y después de plegar, puede encontrar que realmente se define en la cola con Flush, SetcretryCount, SetTimeOut, Add, Pausa, Dequeue y Clear Methods.
Llamada simple
La copia del código es la siguiente:
var q = new Ded.Queue;
// Establezca el número de reades un poco más alto para hacer frente a las conexiones lentas
P.SetRetryCount (5);
// establecer el tiempo de tiempo de espera
P.SetTimeOut (1000);
// Agregar 2 solicitudes.
Q.Add ({
Método: 'Get',
Uri: '/path/to/file.php?ajax=true'
});
Q.Add ({
Método: 'Get',
Uri: '/path/to/file.php?ajax=true&woe=me'
});
// cola de descarga
Q.Flush ();
// Pausa la cola y guarda las restantes
Q.Pause ();
// Claro.
Q.Clear ();
// Agregar 2 solicitudes.
Q.Add ({
Método: 'Get',
Uri: '/path/to/file.php?ajax=true'
});
Q.Add ({
Método: 'Get',
Uri: '/path/to/file.php?ajax=true&woe=me'
});
// Eliminar la última solicitud de la cola.
q.dequeue ();
// Flush de nuevo
Q.Flush ();
¿Dónde está el puente?
No hay un puente en el código de llamada de arriba, entonces, ¿qué pasa con el puente? Eche un vistazo al ejemplo completo a continuación y encontrará que hay puentes en todas partes:
La copia del código es la siguiente:
<! Doctype html público "-// w3c // dtd html 4.01 // en"
"http://www.w3.org/tr/html4/strict.dtd">
<html>
<Evista>
<meta http-equiv = "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 (ventana, 'cargar', function () {
// lograr.
var q = new Ded.Queue;
P.SetRetryCount (5);
P.SetTimeOut (3000);
VAR items = $ ('elementos');
resultados var = $ ('resultados');
var queue = $ ('Queue-Items');
// Guardar rastrear su solicitud en el cliente
solicitudes var = [];
// Después de cada solicitud de descarga, suscríbase a pasos de procesamiento especiales
q.onflush.subscribe (función (datos) {
results.innerhtml = data;
requests.shift ();
queue.innerhtml = requests.toString ();
});
// Pasos de procesamiento de tiempo de suscripción
q.onfailure.subscribe (function () {
Results.innerhtml += '<span style = "color: rojo;"> ¡error de conexión! </span>';
});
// suscribirse a todos los pasos de procesamiento exitosos x
q.oncomplete.subscribe (function () {
results.innerhtml += '<span style = "color: verde;"> completado! </span>';
});
var actionDisPatcher = function (elemento) {
Switch (elemento) {
Caso 'Flush':
Q.Flush ();
romper;
Caso 'Dequeue':
q.dequeue ();
requests.pop ();
queue.innerhtml = requests.toString ();
romper;
Caso 'Pausa':
Q.Pause ();
romper;
caso 'claro':
Q.Clear ();
solicitudes = [];
queue.innerhtml = '';
romper;
}
};
var addRequest = function (request) {
var data = request.split ('-') [1];
Q.Add ({
Método: 'Get',
URI: 'Bridge-Connection-Queue.php? Ajax = True & S =' + Data,
Parámetros: NULL
});
requests.push (datos);
queue.innerhtml = requests.toString ();
};
addEvent (elementos, 'hacer clic', función (e) {
var e = e || Window.event;
var src = e.target || E.Sracelement;
intentar {
E.PreventDefault ();
}
Catch (ex) {
e.returnValue = false;
}
ActionDispatcher (src.id);
});
VAR adders = $ ('Adders');
addEvent (admites, 'hacer clic', función (e) {
var e = e || Window.event;
var src = e.target || E.Sracelement;
intentar {
E.PreventDefault ();
}
Catch (ex) {
e.returnValue = false;
}
AddRequest (src.id);
});
});
</script>
<style type = "text/css" media = "pantalla">
Cuerpo
{
fuente: 100% Georgia, Times, serif;
}
H1, H2
{
Font-peso: Normal;
}
#ítems de cola
{
Altura: 1.5em;
}
#Agregar-stuff
{
relleno: .5em;
Antecedentes: #DDD;
borde: 1px sólido #bbb;
}
#RESULTADO-AREA
{
relleno: .5em;
borde: 1px sólido #bbb;
}
</style>
</ablo>
<Body id = "Ejemplo">
<div id = "doc">
<h1>
Solicitud de unión asíncrona </h1>
<div id = "cola-Ítems">
</div>
<div id = "add-stuff">
<h2> Agregue una nueva solicitud a la cola </h2>
<ul id = "admites">
<li> <a href = "#" id = "Action-01"> Agregar "01" a la cola </a> </li>
<li> <a href = "#" id = "Action-02"> Agregar "02" a la cola </a> </li>
<li> <a href = "#" id = "Action-03"> Agregar "03" a la cola </a> </li>
</ul>
</div>
<h2> Control de cotización </h2>
<ul id = 'elementos'>
<li> <a href = "#" id = "FLUSH"> FLUSH </a> </li>
<li> <a href = "#" id = "dequeue"> dequeue </a> </li>
<li> <a href = "#" id = "pausa"> pausa </a> </li>
<li> <a href = "#" id = "clare"> clare claro </a> </li>
</ul>
<Div id = "AREA DE RESULTADOS">
<h2>
resultado:
</h2>
<div id = "resultados">
</div>
</div>
</div>
</body>
</html>
En este ejemplo, puede hacer varias acciones, como colas de descarga, colas de pausa, eliminar solicitudes en colas, colas claras, etc. Al mismo tiempo, creo que todos también han experimentado el poder de los puentes.
Resumir
Las ventajas del modo puente también son obvias. Solo enumeraremos algunas ventajas principales:
1. Separe la interfaz y las partes de implementación. Una implementación puede no estar vinculada a una interfaz invariablemente. La implementación de la clase abstracta (función) se puede configurar en el tiempo de ejecución, e incluso un objeto puede cambiar su implementación en el tiempo de ejecución. También desacopla completamente la abstracción y la implementación, que también conduce a las capas, generando así un sistema mejor estructurado.
2. Mejorar la escalabilidad
3. Los detalles de implementación son transparentes para los clientes y pueden ocultar los detalles de implementación de los clientes.
Al mismo tiempo, el modo puente también tiene sus propias desventajas:
Una gran cantidad de clases conducirán a mayores costos de desarrollo y también puede reducir el rendimiento.