Javascript event model code

Source: Internet
Author: User

This section gives a deep dive into the topic about event processing. If you are not familiar with patterns, closures, and object-oriented concepts, I believe you will have a lot to learn about it.

1. event processing mode

In the field of programming, "event processing" is a pattern. When an object changes its status due to external influences, the status change notification is sent to this object or an associated object through a message, so that it can execute corresponding actions. This is the basic principle of event processing. Objects responsible for notifying changes in status are called "messages", and the attributes for executing the response action are called "event proxies ".
For example, the following is an application of simple event processing mode:

Function dispatchEvent (owner, eventType, eventArgs)
{
If (owner & owner ["on" + eventType])
SetTimeout (function () {owner ["on" + eventType] (eventArgs)}, 1 );
}

Function randomSerials (len)
{
Function randomSignal ()
{
Return Math. random ()> 0.5? 1: 0;
}
Var ret = [];
For (var I = 0; I <len; I ++)
{
Ret. push (randomSignal ());
}
Return ret;
}

Function Differ (obl)
{
Var buffer = new Array (obl );
Var time = 0;

This. readBuffer = function ()
{
Var buf = buffer;

Buffer = new Array (obl );
Time = 0;

Return buf;
}

This. bufferSize = function ()
{
Return obl;
}

This. input = function (serials)
{
For (var I = 1; I <serials. length; I ++)
{
Var signal = Math. abs (serials [I]-serials [I-1]);
Buffer [time ++ % obl] = signal;
If (signal)
DispatchEvent (this, "signalchange ",
{Input: serials, time: time, buffer: buffer. slice (0 )});
}
}
}

Var inputSerials = randomSerials (20 );
Alert (inputSerials );
Var diff10 = new Differ (20 );
Diff10.input (inputSerials );
Alert (diff10.readBuffer ());

Diff10.onsignalchange = function (eventArgs)
{
Alert (eventArgs. time );
}

Diff10.input (inputSerials );

In the preceding example, the dispatchEvent function is used to dispatch events. onsignalchange is the event proxy. In this differential system diff10, when the level of the input signal changes (from 0 to 1 or from 1 to 0), the corresponding event onsignalchange is triggered, the current input signal, time sequence, and current output cache are passed into the event handler as event parameters.

Diff10.onsignalchange = function (eventArgs)
{
Alert (eventArgs. time );
}

It is an event processing program specified by the programmer. Here we print the input signal sequence when the input level changes.

2. User event Interface Definition

In the previous example, we defined only a dispatchEvent function for event allocation, but it can also be considered as a complete user event interface. Now let's review this function, find out what it did:

Function dispatchEvent (owner, eventName, eventArgs)
{
If (owner & owner ["on" + eventName])
SetTimeout (function () {owner ["on" + eventName] (eventArgs)}, 1 );
}

This function receives three parameters. The first parameter is an object that specifies the "owner" of the event, that is, who receives and processes the event. In the preceding example, the owner is a Differ object, that is
DispatchEvent (this, "signalchange", {input: serials, time: time, buffer: buffer });
The input owner parameter is this. In fact, the event mode allows other types to be used as the owner of the event assignment, especially in some specific modes. Generally, the event initiator and the event receiver can be different from the same object. You can see this in the Observer mode described in section 4.
The second parameter is a string that represents the event type. It determines the name of the Event Agent. According to the specification of the event model, the name of the Event Agent is "on" + event type, for example, in the above example, the event type is signalchange, and the corresponding event proxy is onsignalchange.
The third parameter is an event parameter object, which determines the parameters passed to the event receiver. In the preceding example, it passes three attributes: input, time, and buffer, represents the current input sequence, sequence, and output cache values when an event occurs.
The content of the dispatchEvent function is very simple. It only ensures that the receiver's event proxy is called and the event parameters are correctly passed into the event proxy. It does not care about how the Event Agent processes event parameters.

3. Event proxy and event registration

In event processing mode, the process of specifying an event processing function for the event agent is called event registration. In the above example, diff10.onsignalchange is an extremely simple event proxy, and its event registration process is also extremely simple-it is completed by directly assigning values.
In fact, depending on the design, the event agent can have more complex registration methods, such as DOM-level-2 addEventListener and removeEventListener, we can also implement similar event registration methods, you can register multiple event handling methods for an event proxy. To implement it, we improved the event interface and modified the above example as follows:

Function EventManager (owner)
{
Owner = owner | this;

This. dispatchEvent = function (eventType, eventArgs)
{
Var events = owner ["on" + eventType];
If (events & typeof (events) = "function ")
Events = [events];
If (owner & events)
{
For (var I = 0; I <events. length; I ++)
{
SetTimeout (
(Function (I) {return function () {events [I] (eventArgs )}
}) (I), 1
);
}
}
}

This. addEventListener = function (eventType, closure)
{
If (owner ["on" + eventType] = null)
{
Owner ["on" + eventType] = [];
}
Var events = owner ["on" + eventType];
If (events & typeof (events) = "function ")
Events = [events];
Events. push (closure );
}

This. removeEventListener = function (eventType, closure)
{
Var events = owner ["on" + eventType];
If (events & typeof (events) = "function ")
Events = [events];

For (var I = 0; I <events. length; I ++)
{
If (events [I] = closure)
Events. splice (I, 1 );
}
}
}

Function randomSerials (len)
{
Function randomSignal ()
{
Return Math. random ()> 0.5? 1: 0;
}
Var ret = [];
For (var I = 0; I <len; I ++)
{
Ret. push (randomSignal ());
}
Return ret;
}

Function Differ (obl)
{
Var buffer = new Array (obl );
Var time = 0;

EventManager. call (this); // apply EnventManager Component.

This. readBuffer = function ()
{
Var buf = buffer;

Buffer = new Array (obl );
Time = 0;

Return buf;
}

This. bufferSize = function ()
{
Return obl;
}

This. input = function (serials)
{
For (var I = 1; I <serials. length; I ++)
{
Var signal = Math. abs (serials [I]-serials [I-1]);
Buffer [time ++ % obl] = signal;
If (signal)
This. dispatchEvent ("signalchange ",
{Input: serials, time: time, buffer: buffer. slice (0 )});
}
}
}

Var inputSerials = randomSerials (20 );
Alert (inputSerials );
Var diff10 = new Differ (20 );
Diff10.input (inputSerials );
Alert (diff10.readBuffer ());

Var eventHandler1 = function (eventArgs ){
Alert (eventArgs. time );
}

Var eventHandler2 = function (eventArgs ){
Alert (eventArgs. buffer );
}

Diff10.addEventListener ("signalchange", eventHandler1 );
Diff10.addEventListener ("signalchange", eventHandler2 );
Diff10.input (inputSerials );

Diff10.removeEventListener ("signalchange", eventHandler1 );

In the above example, we have created an EventManager type and defined three object methods for it. The dispatchEvent method is similar to the previous example and is used to dispatch events, in addition, addEventListener and removeEventListener are used to register and deregister event processing functions.
In the Differ type, we use EventManager. call (this); to apply the EventManager instance to the Differ prototype (the deep mechanism of this problem will be discussed later ). Call this. dispatchEvent to dispatch the event.
When registering an event for the onsignalchange event proxy of the Differ instance, you will find that it is very similar to the standard DOM event model:
Diff10.addEventListener ("signalchange", eventHandler1 );
Diff10.addEventListener ("signalchange", eventHandler2 );
Diff10.removeEventListener ("signalchange", eventHandler1 );

After running this example, you will find that the interesting thing is that diff10.input (inputSerials); the event triggered does not execute eventHandler1 and eventHandler2, but only eventHandler2 is executed because:
Diff10.removeEventListener ("signalchange", eventHandler1 );
The event is triggered before the event. This is because the event mechanism is an "Asynchronous callback" mechanism. We will discuss the synchronization and Asynchronization issues later.

4. Standard mode: Event dispatch and receipt

In event processing mode, the event dispatcher is responsible for sending messages, and the event receiver is responsible for processing messages. In the previous example, they are completed by the same object (Differ.
However, in event processing mode, messages are not sent and received by the same object. In some modes, messages are different objects, the most common mode is the observer mode. The following example of a differential system is rewritten as the observer mode:

Function dispatchEvent (owner, eventType, eventArgs)
{
If (owner & owner ["on" + eventType])
SetTimeout (function () {owner ["on" + eventType] (eventArgs)}, 1 );
}

Function randomSerials (len)
{
Function randomSignal ()
{
Return Math. random ()> 0.5? 1: 0;
}
Var ret = [];
For (var I = 0; I <len; I ++)
{
Ret. push (randomSignal ());
}
Return ret;
}

Function DifferObserver (differ)
{
This. differ = differ;
Differ. setObserver (this );
}

Function Differ (obl)
{
Var buffer = new Array (obl );
Var time = 0;
Var observer = null;

This. input = function (serials)
{
For (var I = 1; I <serials. length; I ++)
{
Var signal = Math. abs (serials [I]-serials [I-1]);
Buffer [time ++ % obl] = signal;
If (signal)
DispatchEvent (observer, "signalchange", {sender: this, input: serials, time: time, buffer: buffer. slice (0 )});
}
}

This. setObserver = function (obs)
{
Observer = obs;
Observer. readBuffer = function ()
{
Var buf = buffer;

Buffer = new Array (obl );
Time = 0;

Return buf;
}
Observer. bufferSize = function ()
{
Return obl;
}
}
}


Var inputSerials = randomSerials (20 );
Alert (inputSerials );
Var diff10 = new Differ (20 );
Diff10.input (inputSerials );
Var diffObs = new DifferObserver (diff10 );
Alert (diffObs. readBuffer ());

DiffObs. onsignalchange = function (eventArgs)
{
If (diff10 = eventArgs. sender)
Alert (eventArgs. time );
}

Diff10.input (inputSerials );

In the preceding example, the event dispatcher is of the Differ type, and the event receiver is of the DifferObserver type. Therefore, the event registration proxy is the property of the DifferObserver. In the event parameter sent, we added an attribute sender that references the actual sending object of the event.

Http://bbs.51js.com/thread-69808-1-1.html by moonlight

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.