هذا هو شرح اقتراح API يمكن ملاحظته لمعالجة الأحداث المريحة والقابلة للتأليف.
EventTarget تكامل EventTarget addEventListener() الاقتراح طريقة .when() على وجه التحديد ، تقوم بإرجاع جديد يمكن Observable يضيف مستمعًا جديدًا للحدث إلى الهدف عند استدعاء طريقة subscribe() . يدعو الملاحظة معالج المشترك next() مع كل حدث.
تتحول Observables إلى معالجة الأحداث والتصفية والإنهاء ، إلى تدفق صريح وتصريح يسهل فهمه وتكوينه من الإصدار الحتمي اليوم ، والذي يتطلب غالبًا مكالمات متداخلة addEventListener()
// Filtering and mapping:
element
. when ( 'click' )
. filter ( ( e ) => e . target . matches ( '.foo' ) )
. map ( ( e ) => ( { x : e . clientX , y : e . clientY } ) )
. subscribe ( { next : handleClickAtPoint } ) ; // Automatic, declarative unsubscription via the takeUntil method:
element . when ( 'mousemove' )
. takeUntil ( document . when ( 'mouseup' ) )
. subscribe ( { next : e => … } ) ;
// Since reduce and some other terminators return promises, they also play
// well with async functions:
await element . when ( 'mousemove' )
. takeUntil ( element . when ( 'mouseup' ) )
. reduce ( ( soFar , e ) => … ) ; // Imperative
const controller = new AbortController ( ) ;
element . addEventListener ( 'mousemove' , e => {
console . log ( e ) ;
element . addEventListener ( 'mouseup' , e => {
controller . abort ( ) ;
} ) ;
} , { signal : controller . signal } ) ; تتبع جميع نقرات الارتباطات داخل حاوية (مثال):
container
. when ( 'click' )
. filter ( ( e ) => e . target . closest ( 'a' ) )
. subscribe ( {
next : ( e ) => {
// …
} ,
} ) ; ابحث عن الحد الأقصى لإحداثي y أثناء الاحتفاظ بالماوس (مثال):
const maxY = await element
. when ( 'mousemove' )
. takeUntil ( element . when ( 'mouseup' ) )
. map ( ( e ) => e . clientY )
. reduce ( ( soFar , y ) => Math . max ( soFar , y ) , 0 ) ; تعدد الإرسال WebSocket ، بحيث يتم إرسال رسالة اشتراك على الاتصال ، ويتم إرسال رسالة إلغاء الاشتراك إلى الخادم عندما يقوم المستخدم بإلغاء الاشتراك.
const socket = new WebSocket ( 'wss://example.com' ) ;
function multiplex ( { startMsg , stopMsg , match } ) {
if ( socket . readyState !== WebSocket . OPEN ) {
return socket
. when ( 'open' )
. flatMap ( ( ) => multiplex ( { startMsg , stopMsg , match } ) ) ;
} else {
socket . send ( JSON . stringify ( startMsg ) ) ;
return socket
. when ( 'message' )
. filter ( match )
. takeUntil ( socket . when ( 'close' ) )
. takeUntil ( socket . when ( 'error' ) )
. map ( ( e ) => JSON . parse ( e . data ) )
. finally ( ( ) => {
socket . send ( JSON . stringify ( stopMsg ) ) ;
} ) ;
}
}
function streamStock ( ticker ) {
return multiplex ( {
startMsg : { ticker , type : 'sub' } ,
stopMsg : { ticker , type : 'unsub' } ,
match : ( data ) => data . ticker === ticker ,
} ) ;
}
const googTrades = streamStock ( 'GOOG' ) ;
const nflxTrades = streamStock ( 'NFLX' ) ;
const googController = new AbortController ( ) ;
googTrades . subscribe ( { next : updateView } , { signal : googController . signal } ) ;
nflxTrades . subscribe ( { next : updateView , ... } ) ;
// And the stream can disconnect later, which
// automatically sends the unsubscription message
// to the server.
googController . abort ( ) ; // Imperative
function multiplex ( { startMsg , stopMsg , match } ) {
const start = ( callback ) => {
const teardowns = [ ] ;
if ( socket . readyState !== WebSocket . OPEN ) {
const openHandler = ( ) => start ( { startMsg , stopMsg , match } ) ( callback ) ;
socket . addEventListener ( 'open' , openHandler ) ;
teardowns . push ( ( ) => {
socket . removeEventListener ( 'open' , openHandler ) ;
} ) ;
} else {
socket . send ( JSON . stringify ( startMsg ) ) ;
const messageHandler = ( e ) => {
const data = JSON . parse ( e . data ) ;
if ( match ( data ) ) {
callback ( data ) ;
}
} ;
socket . addEventListener ( 'message' , messageHandler ) ;
teardowns . push ( ( ) => {
socket . send ( JSON . stringify ( stopMsg ) ) ;
socket . removeEventListener ( 'message' , messageHandler ) ;
} ) ;
}
const finalize = ( ) => {
teardowns . forEach ( ( t ) => t ( ) ) ;
} ;
socket . addEventListener ( 'close' , finalize ) ;
teardowns . push ( ( ) => socket . removeEventListener ( 'close' , finalize ) ) ;
socket . addEventListener ( 'error' , finalize ) ;
teardowns . push ( ( ) => socket . removeEventListener ( 'error' , finalize ) ) ;
return finalize ;
} ;
return start ;
}
function streamStock ( ticker ) {
return multiplex ( {
startMsg : { ticker , type : 'sub' } ,
stopMsg : { ticker , type : 'unsub' } ,
match : ( data ) => data . ticker === ticker ,
} ) ;
}
const googTrades = streamStock ( 'GOOG' ) ;
const nflxTrades = streamStock ( 'NFLX' ) ;
const unsubGoogTrades = googTrades ( updateView ) ;
const unsubNflxTrades = nflxTrades ( updateView ) ;
// And the stream can disconnect later, which
// automatically sends the unsubscription message
// to the server.
unsubGoogTrades ( ) ; نحن هنا نستفيد من الملاحظات لمطابقة رمز سري ، وهو نمط من المفاتيح التي قد يضغط عليها المستخدم أثناء استخدام تطبيق:
const pattern = [
'ArrowUp' ,
'ArrowUp' ,
'ArrowDown' ,
'ArrowDown' ,
'ArrowLeft' ,
'ArrowRight' ,
'ArrowLeft' ,
'ArrowRight' ,
'b' ,
'a' ,
'b' ,
'a' ,
'Enter' ,
] ;
const keys = document . when ( 'keydown' ) . map ( e => e . key ) ;
keys
. flatMap ( firstKey => {
if ( firstKey === pattern [ 0 ] ) {
return keys
. take ( pattern . length - 1 )
. every ( ( k , i ) => k === pattern [ i + 1 ] ) ;
}
} )
. filter ( matched => matched )
. subscribe ( ( ) => console . log ( 'Secret code matched!' ) ) ; const pattern = [ ... ] ;
// Imperative
document . addEventListener ( 'keydown' , e => {
const key = e . key ;
if ( key === pattern [ 0 ] ) {
let i = 1 ;
const handler = ( e ) => {
const nextKey = e . key ;
if ( nextKey !== pattern [ i ++ ] ) {
document . removeEventListener ( 'keydown' , handler )
} else if ( pattern . length === i ) {
console . log ( 'Secret code matched!' ) ;
document . removeEventListener ( 'keydown' , handler )
}
} ;
document . addEventListener ( 'keydown' , handler ) ;
}
} , { once : true } ) ;Observable الملاحظات هي كائنات من الدرجة الأولى التي تمثل الأحداث المتكررة القابلة للتكوين. إنهم مثل الوعود ولكن بالنسبة للأحداث المتعددة ، وبالتحديد مع تكامل EventTarget ، فإنهم هو للأحداث التي تعود بالتراجع. يمكن أن تكون:
subscribe()Observable.map() والأفضل من ذلك ، أن الانتقال من معالجات الأحداث ➡ هو أبسط من تلك التي تعود عمليات الاسترجاعات ، لأن الملاحظات تدمج بشكل جيد على رأس EventTarget ، طريقة الاشتراك الواقعية في الأحداث من النظام الأساسي والبرنامج النصي المخصص. نتيجةً لذلك ، يمكن للمطورين استخدام Observables دون ترحيل أطنان من التعليمات البرمجية على النظام الأساسي ، نظرًا لأنها سهلة في أي مكان تتعامل فيه مع الأحداث اليوم.
يمكن العثور على شكل API المقترح في https://wicg.github.io/observable/#core-infrancture.
يمر خالق مرور يمكن ملاحظته في رد اتصال يتم استدعاؤه بشكل متزامن كلما تم استدعاء subscribe() . يمكن تسمية طريقة subscribe() أي عدد من المرات ، ويستدعي رد الاتصال الذي يستدعي إعداد "اشتراك" جديد عن طريق تسجيل المتصل subscribe() كمراقب. مع وجود هذا في مكانه ، يمكن للملاحظة أن يشير إلى أي عدد من الأحداث إلى المراقب عبر رد الاتصال next() ، متبوعًا اختياريًا مكالمة واحدة إلى إما complete() أو error() ، مما يشير إلى انتهاء دفق البيانات.
const observable = new Observable ( ( subscriber ) => {
let i = 0 ;
setInterval ( ( ) => {
if ( i >= 10 ) subscriber . complete ( ) ;
else subscriber . next ( i ++ ) ;
} , 2000 ) ;
} ) ;
observable . subscribe ( {
// Print each value the Observable produces.
next : console . log ,
} ) ; على الرغم من أن الملاحظات المخصصة يمكن أن تكون مفيدة من تلقاء نفسها ، فإن حالة الاستخدام الأساسي التي تفتحها هي معالجة الأحداث. Observables التي تم إرجاعها بواسطة EventTarget#when() أصليًا مع رد اتصال داخلي يستخدم نفس الآلية الأساسية مثل addEventListener() . لذلك ، يقوم استدعاء subscribe() بشكل أساسي بتسجيل مستمع حدث جديد تتعرض أحداثه من خلال وظائف معالج المراقب وقابل للتأليف مع مختلف المتجدات المتاحة لجميع الملاحظات.
يمكن إنشاء Observables بواسطة مُنشئها الأصلي ، كما هو موضح أعلاه ، أو بالطريقة الثابتة Observable.from() . تقوم هذه الطريقة ببناء مواطن يمكن ملاحظته من الكائنات التي هي أي مما يلي ، بهذا الترتيب :
Observable (وفي هذه الحالة ، تُرجع فقط الكائن المحدد)AsyncIterable (أي شيء مع Symbol.asyncIterator )Iterable (أي شيء مع Symbol.iterator .Promise (أو أي وقت مضى) علاوة على ذلك ، فإن أي طريقة على النظام الأساسي الذي يرغب في قبول وسيطة على شبكة الإنترنت ، أو إرجاع واحدة من رد الاتصال الذي يمكن Observable يمكن ملاحظته مع أي من الكائنات المذكورة أعلاه ، والتي يتم تحويلها تلقائيًا إلى مراقبة. يمكننا إنجاز هذا بإحدى طريقتين سننتهي به في المواصفات الملحوظة:
Observable نوع IDL على الويب الخاص الذي يقوم بتنفيذ كائن ECMASCRIPT هذا التحويل IDL على الويب تلقائيًا ، مثل Web IDL يفعل لأنواع أخرى.any ، وتستدعي النثر المواصفات المقابل على الفور خوارزمية تحويل بأن المواصفات التي يمكن ملاحظتها ستوفرها. هذا مشابه لما يفعله معيار التدفقات مع Teerables Async اليوم.تميل المحادثة في #60 نحو الخيار (1).
من الأهمية بمكان ، أن الملاحظات "كسول" من حيث أنها لا تبدأ في انبعاث البيانات حتى يتم الاشتراك فيها ، ولا تصطف أي بيانات قبل الاشتراك. يمكنهم أيضًا البدء في انبعاث البيانات بشكل متزامن أثناء الاشتراك ، على عكس الوعود التي تقوم دائمًا بتصوير مخططات microtasks عند استدعاء .then() . النظر في هذا المثال:
el . when ( 'click' ) . subscribe ( { next : ( ) => console . log ( 'One' ) } ) ;
el . when ( 'click' ) . find ( ( ) => { … } ) . then ( ( ) => console . log ( 'Three' ) ) ;
el . click ( ) ;
console . log ( 'Two' ) ;
// Logs "One" "Two" "Three" باستخدام AbortController ، يمكنك إلغاء الاشتراك من مراقبة حتى عندما ينبعث منه البيانات بشكل متزامن أثناء الاشتراك:
// An observable that synchronously emits unlimited data during subscription.
let observable = new Observable ( ( subscriber ) => {
let i = 0 ;
while ( true ) {
subscriber . next ( i ++ ) ;
}
} ) ;
let controller = new AbortController ( ) ;
observable . subscribe ( {
next : ( data ) => {
if ( data > 100 ) controller . abort ( ) ;
} } , { signal : controller . signal } ,
} ) ; من الأهمية بمكان أن يتمكن المشترك الذي يمكن ملاحظته من تسجيل رد اتصال تعسفي للدموع لتنظيف أي موارد ذات صلة بالاشتراك. يمكن تسجيل teardown من داخل رد الاتصال الاشتراك الذي تم تمريره إلى المُنشئ Observable . عند التشغيل (عند الاشتراك) ، يمكن لاستدعاء الاشتراك تسجيل وظيفة teardown عبر subscriber.addTeardown() .
addTeardown() تم بالفعل إحباط المشترك ( true ، subscriber.signal.aborted . خلاف ذلك ، يتم استدعاءها بشكل متزامن:
complete() ، بعد استدعاء المعالج الكامل للمشترك (إن وجد)error() ، بعد استدعاء معالج خطأ المشترك (إن وجد) نقترح المشغلين التاليين بالإضافة إلى الواجهة Observable :
catch()Promise#catch() ، يتطلب رد اتصال يتم إطلاقه بعد أخطاء المصدر. بعد ذلك ، سيتم تعيينه إلى جديد يمكن ملاحظته ، تم إرجاعه بواسطة رد الاتصال ، ما لم يتم إعادة صياغة الخطأ.takeUntil(Observable)finally()complete() error() Promise.finally()Observable التي تعكس المصدر يمكن ملاحظته بالضبط. يتم إرسال رد الاتصال إلى finally عند إنهاء الاشتراك في الملاحظة الناتجة لأي سبب من الأسباب . إما بعد اكتمال المصدر مباشرة أو الأخطاء ، أو عندما يقوم المستهلك بإلغاء الاشتراك عن طريق إحباط الاشتراك. غالبًا ما تكون إصدارات ما ورد أعلاه موجودة في تطبيقات Userland لـ Observables لأنها مفيدة لأسباب محددة يمكن ملاحظتها ، ولكن بالإضافة إلى ذلك ، فإننا نقدم مجموعة من المشغلين الشائعين الذين يتبعون سابقة النظام الأساسي ويمكننا زيادة فائدة وتبني بشكل كبير. هذه موجودة على المواد القابلة للتكرار الأخرى ، وهي مستمدة من اقتراح مساعدي Iterator TC39 الذي يضيف الطرق التالية إلى Iterator.prototype :
map()filter()take()drop()flatMap()reduce()toArray()forEach()some()every()find() والطريقة التالية بشكل ثابت على مُنشئ Iterator :
from() نتوقع من مكتبات Userland أن توفر المزيد من مشغلي المتخصصين الذين يتكاملون مع واجهة برمجة التطبيقات (API) التي Observable في هذا الاقتراح ، وربما الشحن أصلاً إذا حصلوا على زخم كاف للتخرج إلى المنصة. ولكن بالنسبة لهذا الاقتراح الأولي ، نود تقييد مجموعة المشغلين على أولئك الذين يتبعون سابقة المذكورة أعلاه ، على غرار كيفية قيام واجهات برمجة تطبيقات Web Platform التي تم إعلانها بمثابة خصائص أصلية مستوحاة من خريطة TC39 ومجموعة الكائنات. لذلك ، سننظر في معظم مناقشة توسيع هذه المجموعة على أنها خارج نطاق الاقتراح الأولي ، مناسبة للمناقشة في الملحق. يمكن أن يتابع أي ذيل طويل من المشغلين ما إذا كان هناك دعم لواجهة برمجة التطبيقات الأصلية التي يمكن ملاحظتها المقدمة في هذا الشرح.
لاحظ أن المشغلين every() ، find() ، some() ، reduce() يعودون الذين يختلفون جدولة عن تلك الخاصة بالملاحظات ، مما يعني في بعض الأحيان معالجات الأحداث التي تدعو e.preventDefault() سوف تعمل بعد فوات الأوان. انظر قسم المخاوف الذي يذهب إلى مزيد من التفاصيل.
لتوضيح كيفية تناسب الملاحظات مع المشهد الحالي للبدائل التفاعلية الأخرى ، راجع الجدول أدناه وهو محاولة للجمع بين جدولين آخرين يصنفان البدائيات التفاعلية من خلال تفاعلهم مع المنتجين والمستهلكين:
| المفرد | جمع | |||
|---|---|---|---|---|
| مكاني | زمني | مكاني | زمني | |
| يدفع | قيمة | يعد | يمكن ملاحظته | |
| يحذب | وظيفة | ايتراتور غير متزامن | ITERBILE | ايتراتور غير متزامن |
تم اقتراح Observables لأول مرة إلى المنصة في TC39 في مايو من عام 2015. فشل الاقتراح في اكتساب الجر ، ويرجع ذلك جزئيًا إلى بعض المعارضة بأن واجهة برمجة التطبيقات كانت مناسبة لتكون بدائية على مستوى اللغة. في محاولة لتجديد الاقتراح على مستوى أعلى من التجريد ، تم تقديم مشكلة Whatwg DOM في ديسمبر من عام 2017.
في وقت لاحق من عام 2019 ، تم تقديم محاولة لإحياء الاقتراح في مستودع TC39 الأصلي ، والذي تضمن بعض تبسيط API وأضاف الدعم لمشكلة "Hirehose" المتزامنة.
هذا المستودع هو محاولة لتنفس الحياة مرة أخرى في الاقتراح الملحوظ على أمل شحن نسخة منه إلى منصة الويب.
في مناقشة سابقة ، أدرج Ben Lesh العديد من تطبيقات Userland المخصصة للأوامر البدائية التي يمكن ملاحظتها ، منها RXJS هي الأكثر شعبية مع "47،000،000+ تنزيل في الأسبوع ".
start unsubscribe للمراقبة والحصول على Subscription قبل العائد.Actor الخاص بهم ، للسماح بالاشتراكات للتغييرات في الحالة ، كما هو موضح في خطاف useActor . يعد استخدام متطابق يمكن ملاحظته أيضًا جزءًا موثقًا من جهاز Access State عند استخدام Xstate مع SolidJs.{ subscribe(callback: (value: T) => void): () => void } في جهاز التوجيه ورمز efferreddata الخاص بهم. وقد أشار هذا من قبل المشرفين على أنه مستوحى من الملاحظة.{ subscribe(callback: (value: T) => void): () => void } لإشاراتها.{ subscribe(callback: (value: T) => void): () => void } في عدة أماكن{ subscribe(callback: (value: T) => void): () => void } .{ observe_(callback: (value: T)): () => void } .| async وظيفة "أنبوب | async " في القوالب.بالنظر إلى الفن السابق الواسع في هذا المجال ، يوجد "عقد يمكن ملاحظته".
بالإضافة إلى ذلك ، كانت العديد من واجهات برمجة تطبيقات JavaScript تحاول الالتزام بالعقد المحدد من خلال اقتراح Symbol.observable من عام 2015. لتحقيق هذه الغاية ، هناك مكتبة ، قابلة للرسمية ، والتي تتسرب من المهرات (polyfills). يحتوي symbol-observable على 479 حزمة معتمدة على NPM ، ويتم تنزيلها أكثر من 13،000،000 مرة في الأسبوع. هذا يعني أن هناك 479 حزمة على الأقل على NPM التي تستخدم العقد الملحوظ بطريقة ما.
هذا مشابه لكيفية الوعود/مواصفات+ التي تم تطويرها قبل تبني Promise في ES2015 باعتبارها لغة بدائية من الدرجة الأولى.
أحد الشواغل الرئيسية المعبر عنها في مؤشر ترابط Whatwg DOM الأصلي له علاقة بآبار واجهات برمجة التطبيقات لتحليل الوعود على الملاحظة ، مثل first() المقترح (). Footgun المحتملة هنا مع جدولة Microtass وتكامل الأحداث. على وجه التحديد ، فإن الكود الأبرياء التالي لن يعمل دائمًا :
element
. when ( 'click' )
. first ( )
. then ( ( e ) => {
e . preventDefault ( ) ;
// Do something custom...
} ) ; إذا كان Observable#first() يعيد وعدًا يحل عندما يتم إطلاق الحدث الأول على EventTarget ، فسيتم تشغيل الوعد المرفق للمستخدم .then()
element.click() )e.preventDefault() قد حدث بعد فوات الأوان وتم تجاهله بفعاليةفي WebIDL بعد استدعاء رد الاتصال ، يتم استدعاء خوارزمية HTML تنظيفها بعد تشغيل البرنامج النصي ، وتؤدي هذه الخوارزمية إلى نقطة تفتيش في المداخن الدقيقة إذا كانت مكدس JavaScript فارغًا.
بشكل ملموس ، هذا يعني بالنسبة إلى element.click() في المثال أعلاه ، تحدث الخطوات التالية:
element.click() ، يتم دفع سياق تنفيذ JavaScript أولاً على المكدسclick الحدث (الذي تم إنشاؤه أصليًا من خلال التنفيذ Observable#from() ) ، يتم دفع سياق تنفيذ JavaScript آخر على المكدس ، حيث يستعد WebIDL لتشغيل رد الاتصال الداخليObservable#first() . الآن تحتوي قائمة انتظار Microtask على معالج Promise of Promise then() الذي سيؤدي إلى إلغاء الحدث بمجرد تشغيلهclick ، يستمر بقية مسار الحدث نظرًا لعدم إلغاء الحدث أثناء أو مباشرة رد الاتصال. الحدث يفعل كل ما يفعله عادة (إرسال النموذج ، alert() المستخدم ، إلخ)element.click() javaScript ، ويتم تنفيذ سياق التنفيذ النهائي من المكدس ويتم مسح قائمة انتظار المداخن الدقيقة. يتم تشغيل المعالج المرفق .then() شيئان يخففان من هذا القلق. أولاً ، هناك حل بديل بسيط للغاية لتجنب الحالة التي قد تعمل فيها e.preventDefault() بعد فوات الأوان:
element
. when ( 'click' )
. map ( ( e ) => ( e . preventDefault ( ) , e ) )
. first ( ) ; ... أو إذا كان يمكن ملاحظته طريقة .do() (انظر Whatwg/DOM#544 (تعليق)):
element
. when ( 'click' )
. do ( ( e ) => e . preventDefault ( ) )
. first ( ) ; ... أو عن طريق تعديل دلالات first() لأخذ رد اتصال ينتج عنه قيمة تم حل الوعد الذي تم إرجاعه إلى:
el . when ( 'submit' )
. first ( ( e ) => e . preventDefault ( ) )
. then ( doMoreStuff ) ;ثانياً ، يوجد بالفعل "quirk" في النظام الإيكولوجي المزدهر اليوم ، ولا توجد مخاوف أو تقارير خطيرة من ذلك المجتمع بأن المطورين يركضون باستمرار إلى هذا. هذا يعطي بعض الثقة في أن خبز هذا السلوك في منصة الويب لن يكون خطيرًا.
كان هناك الكثير من النقاش حول أي مكان يجب أن تستضيفه في النهاية اقتراح Observables. لا يكون المكان غير منطقي ، حيث إنه يقرر بشكل فعال ما إذا كانت الملاحظات تصبح بدائية على مستوى اللغة ، والتي تشحن في جميع محركات متصفح JavaScript ، أو منصة ويب بدائية (ولكن اختيارية تقنيًا) في بيئات أخرى مثل Node.js (انظر AbortController Promise سبيل المثال).
تدمج Observables عن قصد بلا احتكاك مع الواجهة الرئيسية التي تنبعث من الأحداث ( EventTarget ) وإلغاء البدائية ( AbortController ) التي تعيش في منصة الويب. كما هو مقترح هنا ، تنضم Observables إلى هذا المكون الموجود بقوة من معيار DOM: يعتمد Observables على إرضاء/إجهاض ، والذي يعتمد على EventTarget ، ويعتمد EventTarget على كل من Observables و AbortController/ElmortSignal. نظرًا لأننا نشعر أن Observables يناسب أفضل ما في أوليها الداعمة ، فإن مكان معايير WhatWG ربما يكون أفضل مكان لتعزيز هذا الاقتراح. بالإضافة إلى ذلك ، فإن تضمينات ECMASCRIPT غير ويب مثل Node.js و Deno ستظل قادرة على تبني الملاحظات ، وربما من المحتمل أن تكون ، بالنظر إلى التزامهم بإجهاض وأحداث منصة الويب.
هذا لا يمنع التوحيد المستقبلي للبلاديات التي تنبعث من الأحداث وإلغاء في TC39 في المستقبل ، يمكن أن يتم حلوب الملاحظات نظريًا في وقت لاحق. ولكن في الوقت الحالي ، نحن متحمسون لإحراز تقدم في Whatwg.
في محاولة لتجنب إعادة توحيد هذه المناقشة ، نحث القارئ على رؤية تعليقات المناقشة التالية:
يمنع هذا القسم مجموعة من معايير الويب ومواقف المعايير المشكلات المستخدمة لتتبع حياة الاقتراح الملاحظة خارج هذا المستودع.
تم تصميم Observables لجعل التعامل مع الأحداث أكثر مريحة وقابلة للتكوين. على هذا النحو ، فإن تأثيرهم على المستخدمين النهائيين غير مباشر ، ويأتي إلى حد كبير في شكل المستخدمين الذين يضطرون إلى تنزيل أقل من JavaScript لتنفيذ الأنماط التي يستخدمها المطورون حاليًا مكتبات الطرف الثالث. كما هو مذكور أعلاه في Exployer ، هناك نظام إيكولوجي مرصود من مستخدمي مراقبة ينتج عنه الكثير من البايتات المفرطة التي يتم تنزيلها كل يوم.
في محاولة لتدوين سابقة Userland القوية من واجهة برمجة التطبيقات (API) التي يمكن ملاحظتها ، فإن هذا الاقتراح سيوفر عشرات التطبيقات المخصصة من التنزيل كل يوم.
بالإضافة إلى ذلك ، بصفتها واجهة برمجة تطبيقات مثل EventTarget و AbortController والآخر المتعلق بـ Promise S ، فإنه يمكّن المطورين من بناء تدفقات معالجة الأحداث الأقل تعقيدًا عن طريق إنشاءها بشكل إعلاني ، مما قد يمكّنهم من بناء المزيد من تجارب المستخدم السليمة على الويب.