Answer the question
In order to leave comments, you need to log in
How to organize OOP logic in JavaScipt using an audio player as an example?
Hi everybody. The bottom line is that a large audio-video player is being written, in which there are a lot of interface elements and events. All modules are native, which were written independently in pure JS (their constructors can be seen below). The approximate number of lines of code before refactoring is 3500. How accurate is this structure for such a project and what design solutions can be used here? PS The code is sketched out just for clarity of how the structure is organized (in fact, everything is more voluminous and less readable).
var PlayerApp = (function() {
// В замыкании храним очень много элементов интерфейса и модулей
var audio = null;
var startButton = $('button.start');
var audioAnalyser = new AudioAnalyser(audio);
var cvsVisualizator = new CanvasVisualizator($('#audio-visualization'));
function bindEvents() {
startButton.addEventListener('click', startPlayHandler);
// Куча других привязок к событиям
function startPlayHandler() {
}
}
//Ниже конструкторы для канваса и web audio API, с помощью которого мы делаем спектр-визулизатор на канвасе
function AudioAnalyser(audio) {
//что-то делаем
}
function CanvasVisualizator(container) {
//что-то делаем
}
return {
init : function() {
bindEvents();
//...
},
play : function() {
}
// остальные публичные методы
}
})();
Answer the question
In order to leave comments, you need to log in
Do you understand that this has nothing to do with OOP? They are just objects containing functions, not real objects. Well, that is, you don't have constructors, you have "modules".
Yes, and how would such things as validation, etc. can be organized as pure functions, minimize state mutations and keep it simple.
Also use modules, they will help you remove unnecessary nesting levels and achieve isolation, the code will become tidier.
Less imperative logic, more declarative behavior. If there are really a lot of events, you can try to look towards observable and event streams.
Great question! I myself have been wondering this problem for a long time. As a backend developer, I understood the need but did not know how to implement the structure so that there would be no mess.
The solution that helped: you need to ensure that there are no DOM calls in the PlayerApp at all. By the way, then jQuery will not be needed inside the PlayerApp. There should be only audio context, nodes, analyzer, etc. But this will make the code much simpler, cleaner and more understandable.
For example PlayerApp.js might look like this
(function() {
var PlayerApp, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments) } }
PlayerApp = (function() {
function PlayerApp(url) {
this.play = __bind(this.play, this)
// другие __bind здесь, stop, resume, etc...
this.audio = new Audio()
this.audio.volume = 1
this.audio.src = url
this.audio.addEventListener("canplaythrough", this.canplay, false)
// другие addEventListener здесь: loadedmetadata, timeupdate, etc...
}
Track.prototype.play = function() {
this.audio.play()
if (typeof this.onplay_callback == "function") { this.onplay_callback() }
}
// другие функции здесь ....
return PlayerApp
})()
window.PlayerApp = PlayerApp
}).call(this)
player = new PlayerApp()
player.onplay_callback = function() {
$("#main-play-btn").toggleClass('play')
$(".playlist-play-btn").toggleClass('play')
}
use closures instead of functions.
something like this
var Valid = (function () {
//import dom
var Rule = {
required: function (string) {
if (string.length > 0) {
return true;
}
return false;
},
min: function (string, count) {
if (string.length > count) {
return true;
}
return false;
},
max: function (string, count) {
console.info(count);
console.info(string.length);
if (string.length <= count) {
return true;
}
return false;
},
email: function (string){
var re = /^(([^<>()\[\]\\.,;:\[email protected]"]+(\.[^<>()\[\]\\.,;:\[email protected]"]+)*)|(".+"))@((\ === undefined) {
var rulesP = rules[i].split(":");
if (Rule[rulesP[0]] === undefined) {
console.warn("У валидатора нету правила " + rulesP[0]);
} else {
if (!Rule[rulesP[0]](string, rulesP[1])) {
dom.UpID(id, template[0]+message[rulesP[0]]+template[1]);
return false;
}
}
} else {
if (!Rule[rules[i]](string)) {
dom.UpID(id, template[0]+message[rules[i]]+template[1]);
return false;
}
}
}
return true;
};
return {
Make: function (rule, message, template) {
var key;
for (key in rule) {
var id = key + "_error";
dom.ClearID(id);
//ошибка. Завершаем валидацию.
if (!cc(dom.form.GetInputID(key), rule[key], id, message[key], template)) {
return false;
}
}
return true;
}
};
}());
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question