يقدم
يفصل وضع الجسر الأجزاء المجردة عن أجزاء التنفيذ الخاصة به بحيث يمكن تغييرها جميعًا بشكل مستقل.
نص
يتم استخدام وضع الجسر بشكل شائع في مراقبة الأحداث. دعونا أولاً نلقي نظرة على قطعة من الكود:
نسخة الكود كما يلي:
addEvent (عنصر ، "انقر" ، getBeerById) ؛
وظيفة getBeerbyid (e) {
var id = this.id ؛
Asyncrequest ('get' ، 'beer.uri؟ id =' + id ، function (resp) {
// استجابة رد الاتصال.
console.log ('requested beer:' + resp.sponsetext) ؛
}) ؛
}
هناك مشكلة في الكود أعلاه الذي يجب أن يكون لدى GetBeerByid سياق المتصفح لاستخدامه ، لأنه يستخدم هذا. إذا لم يتم استخدام السياق ، فسيكون ذلك بمثابة توقف. لذلك ، بشكل عام ، سيقوم المبرمج ذو الخبرة قليلاً بتحويل البرنامج إلى النموذج التالي:
نسخة الكود كما يلي:
وظيفة getBeerById (معرف ، رد الاتصال) {
// أرسل الطلب عبر المعرف وأرجع البيانات
Asyncrequest ('get' ، 'beer.uri؟ id =' + id ، function (resp) {
// استجابة رد الاتصال
رد الاتصال (resp.sponsetext) ؛
}) ؛
}
أكثر عملية ، أليس كذلك؟ أولاً ، يمكن تمرير المعرف في الإرادة ، ويتم توفير وظيفة رد الاتصال أيضًا لوظائف المعالجة المخصصة. ولكن ما علاقة هذا مع الجسر؟ هذا ما سيعكسه الرمز التالي:
نسخة الكود كما يلي:
addEvent (العنصر ، "انقر" ، getBeerbyidbridge) ؛
وظيفة getBeerbyidbridge (e) {
getBeerbyid (this.id ، وظيفة (بيرة) {
console.log ('requested beer:'+beer) ؛
}) ؛
}
هنا ، GetBeerbyidbridge هو الجسر الذي نحدده ، والذي يتم استخدامه لتوصيل حدث النقر التجريدي و GetBeerById ، وفي الوقت نفسه تمرير معرف مصدر الحدث ووظيفة الاتصال المخصصة (Console.log Output) في وظيفة getBeerById كمعلمات.
يبدو هذا المثال بسيطًا بعض الشيء ، دعنا نأخذ مثالًا عمليًا آخر أكثر تعقيدًا.
قائمة انتظار اتصال XHR الفعلية
نريد إنشاء قائمة انتظار ، والتي تخزن العديد من طلبات Ajax في قائمة الانتظار. يرجع استخدام قوائم الانتظار بشكل أساسي لأننا بحاجة إلى التأكد من معالجة الطلبات التي يتم ربطها أولاً. في أي وقت ، يمكننا إيقاف الطلبات ، وحذف الطلبات ، وطلبات إعادة المحاولة ، ودعم أحداث الاشتراك لكل طلب.
الوظائف الأساسية الأساسية
قبل البدء الرسمي ، دعنا نحدد العديد من وظائف التغليف الأساسية. أولاً ، الأول هو تغليف وظيفة الطلبات غير المتزامنة:
نسخة الكود كما يلي:
var asyncrequest = (function () {
وظيفة HandlerEadyState (O ، رد الاتصال) {
var poll = window.setinterval (
وظيفة () {
if (O && o.ReadyState == 4) {
window.clearinterval (استطلاع) ؛
إذا (رد الاتصال) {
رد الاتصال (O) ؛
}
}
} ،
50
) ؛
}
var getxhr = function () {
var http ؛
يحاول {
http = new xmlhttprequest ؛
getxhr = function () {
إرجاع xmlhttprequest جديد ؛
} ؛
}
catch (e) {
var msxml = [
'msxml2.xmlhttp.3.0' ،
'msxml2.xmlhttp' ،
'microsoft.xmlhttp'
] ؛
لـ (var i = 0 ، len = msxml.length ؛ i <len ؛ ++ i) {
يحاول {
http = new ActivexObject (msxml [i]) ؛
getxhr = function () {
إرجاع New ActivexObject (msxml [i]) ؛
} ؛
استراحة؛
}
catch (e) {}
}
}
إرجاع http ؛
} ؛
وظيفة الإرجاع (الطريقة ، URI ، رد الاتصال ، postdata) {
var http = getxhr () ؛
http.open (الطريقة ، uri ، صواب) ؛
HandlerEadyState (HTTP ، رد الاتصال) ؛
http.send (postdata || null) ؛
إرجاع http ؛
} ؛
}) () ؛
وظيفة التنفيذ الذاتي المغلفة هي وظيفة طلب AJAX عامة ، وأعتقد أن أي شخص لديه السمة يمكن أن يفهمها Ajax.
بعد ذلك نحدد طريقة عامة لإضافة طرق (وظائف):
نسخة الكود كما يلي:
function.prototype.method = function (name ، fn) {
this.prototype [name] = fn ؛
إرجاع هذا ؛
} ؛
أخيرًا ، أضف طريقتين حول المصفوفات ، واحدة للتجبر وواحدة للتصفية:
نسخة الكود كما يلي:
if (! array.prototype.foreach) {
Array.Method ('foreach' ، function (fn ، thisobj) {
var scope = thisobj || نافذة
لـ (var i = 0 ، len = this.length ؛ i <len ؛ ++ i) {
fn.call (النطاق ، هذا [i] ، أنا ، هذا) ؛
}
}) ؛
}
if (! array.prototype.filter) {
Array.Method ('filter' ، function (fn ، thisobj) {
var scope = thisobj || نافذة
var a = [] ؛
لـ (var i = 0 ، len = this.length ؛ i <len ؛ ++ i) {
إذا (! fn.call (النطاق ، هذا [i] ، أنا ، هذا)) {
يكمل؛
}
A.Push (هذا [i]) ؛
}
إرجاع أ ؛
}) ؛
}
نظرًا لأن بعض المتصفحات الجديدة تدعم بالفعل هاتين الوظيفتين (أو بعض المكتبات الصف التي تدعمها بالفعل) ، يجب علينا أولاً الحكم إذا كانت مدعومة بالفعل ، وإذا كانت مدعومة بالفعل ، فلن تتم معالجتها بعد الآن.
نظام المراقب
يلعب المراقبون دورًا مهمًا في عملية الأحداث في قائمة الانتظار ويمكنهم الاشتراك في الأحداث عند قائمة الانتظار (النجاح ، الفشل ، المعلق):
نسخة الكود كما يلي:
window.ded = window.ded || {} ؛
ded.Util = ded.Util || {} ؛
ded.util.observer = function () {
this.fns = [] ؛
}
ded.util.observer.prototype = {
الاشتراك: وظيفة (fn) {
this.fns.push (fn) ؛
} ،
إلغاء الاشتراك: وظيفة (fn) {
this.fns = this.fns.filter (
وظيفة (el) {
إذا (el! == fn) {
إرجاع EL ؛
}
}
) ؛
} ،
النار: وظيفة (س) {
this.fns.foreach (
وظيفة (el) {
el (o) ؛
}
) ؛
}
} ؛
رمز قائمة الانتظار الرئيسي
أولاً ، يمكنك الاشتراك في السمات الرئيسية ومندوبي الأحداث في قائمة الانتظار:
نسخة الكود كما يلي:
ded.queue = function () {
// يحتوي على قائمة الانتظار للطلبات.
this.queue = [] ؛
// استخدم كائنًا يمكن ملاحظته على 3 حالات مختلفة حتى تتمكن من الاشتراك في الأحداث في أي وقت
this.oncomplete = new ded.util.observer ؛
this.onfailure = new ded.util.observer ؛
this.onflush = new ded.util.observer ؛
// يمكن تعيين الخصائص الأساسية أثناء المكالمات الخارجية
this.retryCount = 3 ؛
this.currentRetry = 0 ؛
this.paused = false ؛
this.timeout = 5000 ؛
this.conn = {} ؛
this.timer = {} ؛
} ؛
بعد ذلك ، من خلال Call of Ded.Queue.Method ، تتم إضافة العديد من الأساليب المتاحة إلى قائمة الانتظار:
نسخة الكود كما يلي:
Ded.queue.
الطريقة ('Flush' ، function () {
// طريقة التدفق
if (! this.queue.length> 0) {
يعود؛
}
إذا (this.paused) {
this.paused = false ؛
يعود؛
}
var that = هذا ؛
this.currentRetry ++ ؛
var apport = function () {
that.conn.abort () ؛
if (that.currentRetry == that.retryCount) {
that.onfailure.fire () ؛
that.currentRetry = 0 ؛
} آخر {
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 () ؛
يعود؛
}
// دعوة متكررة للتدفق
that.flush () ؛
} ؛
this.conn = Asyncrequest (
this.queue [0] ['method'] ،
this.queue [0] ['uri'] ،
أتصل مرة أخرى،
this.queue [0] ['params']
) ؛
}).
الطريقة ('setRetryCount' ، الدالة (العد) {
this.retryCount = count ؛
}).
الطريقة ('setTimeout' ، وظيفة (الوقت) {
this.timeout = الوقت ؛
}).
الطريقة ("إضافة" ، دالة (O) {
this.queue.push (o) ؛
}).
الطريقة ("الإيقاف المؤقت" ، الدالة () {
this.paused = true ؛
}).
الطريقة ('dequeue' ، function () {
this.queue.pop () ؛
}).
الطريقة ('clear' ، function () {
this.queue = [] ؛
}) ؛
يبدو الكود كثيرًا ، وبعد طي ، يمكنك العثور على أنه يتم تعريفه فعليًا على قائمة الانتظار باستخدام طرق Flush و SetRetryCount و SetTimeout و Add و Pause و Dequeue و Clear.
مكالمة بسيطة
نسخة الكود كما يلي:
var q = new ded.queue ؛
// قم بتعيين عدد المحاكاة أعلى قليلاً للتعامل مع الاتصالات البطيئة
Q.SetRetryCount (5) ؛
// تعيين وقت المهلة
Q.SetTimeout (1000) ؛
// إضافة 2 طلبات.
Q.Add ({
الطريقة: "الحصول على" ،
uri: '/path/to/file.php؟ajax=true'
}) ؛
Q.Add ({
الطريقة: "الحصول على" ،
uri: '/path/to/file.php؟ajax=true&woe=me'
}) ؛
// قائمة الانتظار
q.flush () ؛
// إيقاف قائمة الانتظار وحفظ تلك المتبقية
Q.Pause () ؛
// واضح.
Q.clear () ؛
// إضافة 2 طلبات.
Q.Add ({
الطريقة: "الحصول على" ،
uri: '/path/to/file.php؟ajax=true'
}) ؛
Q.Add ({
الطريقة: "الحصول على" ،
uri: '/path/to/file.php؟ajax=true&woe=me'
}) ؛
// حذف الطلب الأخير من قائمة الانتظار.
Q.Dequeue () ؛
// تدفق مرة أخرى
q.flush () ؛
أين الجسر؟
لا يوجد جسر في رمز الاتصال أعلاه ، فماذا عن الجسر؟ ألقِ نظرة على المثال الكامل أدناه وستجد أن هناك جسورًا في كل مكان:
نسخة الكود كما يلي:
<! doctype html public "-// w3c // dtd html 4.01 // en"
"http://www.w3.org/tr/html4/strict.dtd">
<html>
<head>
<meta http-equiv = "content-type" content = "text/html ؛ charset = utf-8">
<title> قائمة انتظار اتصال Ajax </title>
<script src = "utils.js"> </script>
<script src = "queue.js"> </script>
<script type = "text/javaScript">
addEvent (نافذة ، "تحميل" ، دالة () {
// ينجز.
var q = new ded.queue ؛
Q.SetRetryCount (5) ؛
Q.Settimeout (3000) ؛
VAR stems = $ ('items') ؛
نتائج var = $ ('النتائج') ؛
Queue var = $ ('Queue-Intems') ؛
// احفظ تتبع طلبك على العميل
طلبات var = [] ؛
// بعد كل طلب للتدفق ، اشترك في خطوات المعالجة الخاصة
Q.Onflush.subscribe (وظيفة (البيانات) {
النتائج. innerhtml = البيانات ؛
requests.shift () ؛
queue.innerhtml = requests.toString () ؛
}) ؛
// خطوات معالجة وقت الاشتراك
Q.Onfailure.subscribe (function () {
النتائج.
}) ؛
// اشترك في جميع خطوات المعالجة الناجحة x
Q.Oncomplete.subscribe (function () {
النتائج.
}) ؛
var actionDispatcher = function (element) {
التبديل (عنصر) {
حالة "تدفق":
q.flush () ؛
استراحة؛
حالة "dequeue":
Q.Dequeue () ؛
requests.pop () ؛
queue.innerhtml = requests.toString () ؛
استراحة؛
حالة "توقف مؤقت":
Q.Pause () ؛
استراحة؛
حالة "واضحة":
Q.clear () ؛
الطلبات = [] ؛
queue.innerhtml = '' ؛
استراحة؛
}
} ؛
var addrequest = function (request) {
var data = request.split ('-') [1] ؛
Q.Add ({
الطريقة: "الحصول على" ،
URI: 'bridge-connection-queue.php؟ ajax = true & s =' + data ،
params: فارغة
}) ؛
requests.push (data) ؛
queue.innerhtml = requests.toString () ؛
} ؛
addEvent (عناصر ، "انقر" ، وظيفة (e) {
var e = e || window.event ؛
var src = e.target || E.Srcelement ؛
يحاول {
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.target || E.Srcelement ؛
يحاول {
E.PreventDefault () ؛
}
catch (ex) {
e.ReturnValue = false ؛
}
addrequest (src.id) ؛
}) ؛
}) ؛
</script>
<type type = "text/css" media = "screen">
جسم
{
الخط: 100 ٪ جورجيا ، تايمز ، رقيق ؛
}
H1 ، H2
{
خط الوزن: طبيعي ؛
}
#قائمة الانتظار
{
الارتفاع: 1.5EM ؛
}
#add-stuff
{
الحشو: .5em ؛
الخلفية: #DDD ؛
الحدود: 1 بكسل Solid #BBB ؛
}
#النتائج
{
الحشو: .5em ؛
الحدود: 1 بكسل Solid #BBB ؛
}
</style>
</head>
<body id = "example">
<div id = "doc">
<H1>
طلب انضمام غير متزامن </h1>
<div id = "queue-items">
</div>
<div id = "add-stuff">
<h2> أضف طلبًا جديدًا إلى قائمة الانتظار </h2>
<ul id = "adders">
<li> <a href = "#" id = "action-01"> إضافة "01" إلى قائمة الانتظار </a> </li>
<li> <a href = "#" id = "action-02"> إضافة "02" إلى قائمة الانتظار </a> </li>
<li> <a href = "#" id = "action-03"> إضافة "03" إلى قائمة الانتظار </a> </li>
</ul>
</div>
<h2> QUOTE CONTROL </h2>
<ul id = 'العناصر'>
<li> <a href = "#" id = "flush"> flush </a> </li>
<li> <a href = "#" id = "dequeue"> dequeue </a> </li>
<li> <a href = "#" id = "pause"> الإيقاف المؤقت </a> </li>
<li> <a href = "#" id = "clear"> clear clear </a> </li>
</ul>
<div id = "نتائج المناطق">
<H2>
نتيجة:
</h2>
<div id = "النتائج">
</div>
</div>
</div>
</body>
</html>
في هذا المثال ، يمكنك القيام بإجراءات مختلفة مثل طوابير التدفق ، وقوائم الإيقاف المؤقت ، وحذف الطلبات في قوائم الانتظار ، وقوائم الانتظار الواضحة ، وما إلى ذلك. في الوقت نفسه ، أعتقد أن الجميع قد عانوا من قوة الجسور.
لخص
مزايا وضع الجسر واضحة أيضا. سنقوم فقط بإدراج بعض المزايا الرئيسية:
1. افصل أجزاء الواجهة والتنفيذ. قد لا يكون التنفيذ مرتبطًا بواجهة دائمًا. يمكن تكوين تنفيذ الفئة التجريدية (الوظيفة) في وقت التشغيل ، ويمكن للكائن حتى تغيير تنفيذه في وقت التشغيل. كما أنه يفصل تمامًا التجريد والتنفيذ ، والذي يفضي أيضًا إلى الطبقات ، وبالتالي توليد نظام منظم أفضل.
2. تحسين قابلية التوسع
3. تفاصيل التنفيذ شفافة للعملاء ويمكنها إخفاء تفاصيل التنفيذ من العملاء.
في الوقت نفسه ، فإن وضع الجسر له أيضًا عيوبه الخاصة:
سيؤدي عدد كبير من الطبقات إلى زيادة تكاليف التطوير وقد يقلل من الأداء أيضًا.