Mã giao diện người dùng của bạn có thể nhanh chóng trở nên khó sử dụng khi xây dựng một ứng dụng phải phản ứng với nhiều sự kiện khác nhau. Ví dụ: trong một ứng dụng sử dụng ổ cắm web, không có gì lạ khi thấy mã như thế này
mySocket.addEventListener["message", [message] => {
const data = JSON.parse[message.data];
switch [data.event] {
case "NewMessage":
addMessage[message];
addNotification[message];
break;
case "MessageEdited":
changeMessage[message];
someSideEffect[];
break;
// ...etc.
}
}];
Không cần phải nói nếu bạn bắt đầu cần xử lý 20, 30 hoặc 40 sự kiện khác nhau, điều này có thể bắt đầu trở nên rất lộn xộn và nếu chúng ta muốn ngừng nghe một sự kiện cụ thể thì sao? . Rõ ràng phải có một cách tốt hơn để làm mọi việc
Những gì chúng tôi có thể làm gì về nó?
Lý tưởng nhất là chúng tôi có thể chuyển sự kiện và dữ liệu liên quan vào bộ điều phối sự kiện, sau đó sẽ gọi tất cả các chức năng chính xác cho chúng tôi. Chúng tôi cũng có thể dừng chạy một số chức năng - ví dụ: nếu cửa sổ hiện tại đã mở, chúng tôi không muốn tạo thông báo mới
Đến cuối hướng dẫn này, chúng ta sẽ có thể biến đoạn mã trên thành một thứ giống như thế này
const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
Điều này đã bắt đầu có tổ chức và mạnh mẽ hơn nhiều, và điều tốt nhất là chúng tôi có thể yêu cầu trình điều phối này từ bất kỳ đâu trong ứng dụng của mình - cho phép chúng tôi nhóm các sự kiện liên quan thành các tệp riêng biệt và quản lý các sự kiện của mình từ bất kỳ đâu. Chúng tôi cũng có thể có một số bộ điều phối cho các nhóm sự kiện khác nhau hoặc nhiều bộ điều phối cho nhiều kết nối websocket. Cấu trúc thực sự tùy thuộc vào bạn
Hãy học cách xây dựng nó
Xây dựng bộ điều phốiChúng tôi sẽ xây dựng cái này bằng cách sử dụng các lớp es6 để giữ cho mã của chúng tôi gọn gàng và hướng đối tượng. Hãy bắt đầu bằng cách xây dựng khung của các lớp, với mỗi phương thức chúng ta sẽ cần
Lập bản đồ các bộ xương của các lớp
class Dispatcher {
constructor[] {
this.events = {};
}
dispatch[eventName, data] {
// TODO: dispatch the provided event
}
on[eventName, callback] {
// TODO: add the event listener to the provided event
}
off[eventName, callback] {
// TODO: remove the event listener from the provided event
}
}
Chúng tôi đang khởi tạo
const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
1 với một đối tượng trống, đây là nơi chúng tôi sẽ lưu trữ từng sự kiện được liên kết với bộ điều phối này. Các sự kiện cũng sẽ cần các phương thức riêng của chúng, vì vậy chúng ta sẽ phải tạo một lớp const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
2 cho các sự kiệnclass DispatcherEvent {
constructor[eventName] {
this.eventName = eventName;
this.callbacks = [];
}
registerCallback[callback] {
// TODO: Add the provided callback to the event
}
unregisterCallback[callback] {
// TODO: Remove the provided callback from the event
}
fire[data] {
// TODO: Call each callback with the provided data
}
}
Lớp
const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
2 được khởi tạo với const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
4 mà chúng tôi chuyển vào và một mảng const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
5 trống, nơi chúng tôi sẽ lưu trữ từng cuộc gọi lại đã đăng ký cho sự kiệnThực hiện các phương pháp
Bây giờ chúng ta đã có khung của
const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
6 và const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
2, chúng ta có thể bắt đầu triển khai từng phương pháp. Việc thêm một trình lắng nghe sự kiện mới có vẻ là một nơi tốt để bắt đầu, vì vậy hãy bắt đầu với phương thức const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
8on[eventName, callback] {
// First we grab the event from this.events
let event = this.events[eventName];
// If the event does not exist then we should create it!
if [!event] {
event = new DispatcherEvent[eventName];
this.events[eventName] = event;
}
// Now we add the callback to the event
event.registerCallback[callback];
}
Chúng tôi đã sử dụng
const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
9 ở đây, nhưng chúng tôi chưa xây dựng nó. Hãy xây dựng nó tiếp theo để làm cho const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
8 hoạt độngregisterCallback[callback] {
this.callbacks.push[callback];
}
Tất cả những gì chúng ta làm ở đây là đẩy hàm gọi lại đã cho vào mảng gọi lại của sự kiện, đơn giản
Bây giờ chúng ta có thể tạo các sự kiện và thêm các cuộc gọi lại, nhưng điều đó không hữu ích trừ khi chúng ta thực sự có thể chạy các cuộc gọi lại đó. Hãy xây dựng
class Dispatcher {
constructor[] {
this.events = {};
}
dispatch[eventName, data] {
// TODO: dispatch the provided event
}
on[eventName, callback] {
// TODO: add the event listener to the provided event
}
off[eventName, callback] {
// TODO: remove the event listener from the provided event
}
}
1 tiếp theodispatch[eventName, data] {
// First we grab the event
const event = this.events[eventName];
// If the event exists then we fire it!
if [event] {
event.fire[data];
}
}
Để làm việc này, chúng ta cần triển khai phương thức
class Dispatcher {
constructor[] {
this.events = {};
}
dispatch[eventName, data] {
// TODO: dispatch the provided event
}
on[eventName, callback] {
// TODO: add the event listener to the provided event
}
off[eventName, callback] {
// TODO: remove the event listener from the provided event
}
}
2fire[data] {
// We loop over a cloned version of the callbacks array
// in case the original array is spliced while looping
const callbacks = this.callbacks.slice[0];
// loop through the callbacks and call each one
callbacks.forEach[[callback] => {
callback[data];
}];
}
Tất cả những gì chúng tôi làm là lặp lại và gọi từng cuộc gọi lại, dễ dàng phải không? . Tất cả những gì chúng ta cần làm bây giờ là thực hiện loại bỏ người nghe. Hãy bắt đầu với phương pháp
class Dispatcher {
constructor[] {
this.events = {};
}
dispatch[eventName, data] {
// TODO: dispatch the provided event
}
on[eventName, callback] {
// TODO: add the event listener to the provided event
}
off[eventName, callback] {
// TODO: remove the event listener from the provided event
}
}
3off[eventName, callback] {
// First get the correct event
const event = this.events[eventName];
// Check that the event exists and it has the callback registered
if [event && event.callbacks.indexOf[callback] > -1] {
// if it is registered then unregister it!
event.unregisterCallback[callback];
// if the event has no callbacks left, delete the event
if [event.callbacks.length === 0] {
delete this.events[eventName];
}
}
}
Phương thức duy nhất còn lại để triển khai là phương thức
class Dispatcher {
constructor[] {
this.events = {};
}
dispatch[eventName, data] {
// TODO: dispatch the provided event
}
on[eventName, callback] {
// TODO: add the event listener to the provided event
}
off[eventName, callback] {
// TODO: remove the event listener from the provided event
}
}
4, để chúng ta có thể xóa hàm gọi lại khỏi mảng hàm gọi lạiunregisterCallback[callback] {
// Get the index of the callback in the callbacks array
const index = this.callbacks.indexOf[callback];
// If the callback is in the array then remove it
if [index > -1] {
this.callbacks.splice[index, 1];
}
}
Chúng ta đã làm gì?
Phù. Đã được thực hiện. hãy xem thành phẩm của chúng ta trông như thế nào
const myDispatcher = new Dispatcher[];
// Listen for socket messages
mySocket.addEventListener["message", [message] => {
// dispatch the appropriate event
const data = JSON.parse[message.data];
myDispatcher.dispatch[data.event, data];
}];
// Add event listeners for the events that come from the socket
myDispatcher.on["NewMessage", addMessage];
myDispatcher.on["MessageEdited", changeMessage];
myDispatcher.on["MessageEdited", someSideEffect];
// We should also be able to turn event listeners off & back on
window.addEventListener["blur", [] => {
myDispatcher.on["NewMessage", addNotification];
}];
window.addEventListener["focus", [] => {
myDispatcher.off["NewMessage", addNotification];
}];
0Kết thúcĐó là một mã số lượng nhỏ cho rất nhiều chức năng. Đối với mục đích của hướng dẫn này, chúng tôi đã giữ mọi thứ tương đối đơn giản, có một số điều cần lưu ý
Chúng tôi chưa thực hiện bất kỳ xử lý lỗi nào
Chúng tôi chưa kiểm tra xem các đối số thích hợp có được chuyển đến các phương thức hay không
Chúng tôi chưa tối ưu hóa cho hiệu suất
Vì vậy, có chúng tôi. Hãy nghĩ xem bạn có thể thêm chức năng nào khác vào chức năng này để làm cho nó mạnh mẽ hơn nữa và đừng giới hạn trí tưởng tượng của bạn trong việc sử dụng chức năng này với ổ cắm web - nó có thể rất tuyệt vời cho nhiều tình huống khác nhau