Как мне создать клиентскую систему очереди?

Обзор

Я работаю над проектом, и я столкнулся с некоторой проблемой в том, что вещи не происходят в том порядке, в котором я хочу, чтобы они произошли. Поэтому я подумывал о создании какой-то очереди, которую я могу использовать для организации вызовов функций и других разных инструкций JavaScript/jQuery, используемых во время запуска, т.е. При загрузке страницы. То, что я ищу, необязательно должно быть структурой данных очереди, но какая-то система, которая обеспечит выполнение действий в указанном порядке и только когда предыдущая задача будет завершена, может начать новую задачу.

Я кратко рассмотрел jQuery Queue и AjaxQueue, но я действительно не знаю, как они работают, поэтому я не уверен, что это тот подход, который я хочу принять... но я буду продолжать читать больше об этих инструментах.

КОНКРЕТНЫЕ

В настоящее время я установил все, чтобы некоторые работы происходили внутри $(document).ready(function() {...});, а другая работа происходит внутри $(window).load(function() {...});. Например,


... и это действительно утомительно и уродливо, не говоря уже о плохом дизайне. Поэтому вместо того, чтобы иметь дело с этим беспорядком, я хочу создать довольно универсальную систему, чтобы я мог, например, enqueue $().LoadJavaScript();, затем var script = document.createElement("script");, затем $().InitializeSymbols();, затем $().InitializeBlock(); и т.д...., а затем Queue будет выполнять вызовы функций и инструкции, так что после завершения одной команды другой может запуститься, пока очередь не станет пустой, вместо того чтобы я повторно вызывал dequeue.

Обоснование этого состоит в том, что некоторые работы должны выполняться, например, конфигурация и инициализация, прежде чем другая работа начнется из-за зависимости от выполненных шагов конфигурации и инициализации. Если это не похоже на хорошее решение, сообщите мне:)

НЕКОТОРЫЕ ОСНОВНЫЕ РАБОТЫ

Я написал код для базовой очереди, который можно найти здесь, но я хочу расширить его функциональность, чтобы Я могу хранить различные типы "Объектов", например отдельные инструкции JavaScript/jQuery и вызовы функций, в основном фрагменты кода, которые я хочу выполнить.

UPDATE

В текущей реализации Queue, которая была реализована, похоже, что я могу хранить функции и выполнять их позже, например:

// a JS file... 
$.fn.LoadJavaScript = function() {
 $.getScript("js/Symbols/Symbol.js");
 $.getScript("js/Structures/Structure.js");
};
// another JS file...
function init() { // symbols and structures };
// index.html
var theQueue = new Queue();
theQueue.enqueue($().LoadJavaScript);
theQueue.enqueue(init);
var LJS = theQueue.dequeue();
var INIT = theQueue.dequeue();
LJS();
INIT();

Я также думаю, что я понял, как хранить отдельные инструкции, такие как $('#equation').html(""); или, возможно, даже if-else-инструкции или циклы, путем их переноса как таковых:

theQueue.enqueue(function() { $('#equation').html(""); // other instructions, etc... });

Но этот подход потребовал бы, чтобы я подождал, пока очередь будет выполнена с его работой, прежде чем я смогу продолжать выполнять свою работу. Это кажется неправильным дизайном. Есть ли более умный подход к этому? Кроме того, как я могу узнать, что определенная функция завершила выполнение, чтобы Очередь могла знать, чтобы двигаться дальше? Есть ли какое-то возвращаемое значение, которое я могу дождаться или функция обратного вызова, которую я могу указать для каждой задачи в очереди?

WRAP-UP

Так как я делаю все на стороне клиента, и я не могу заставить Очередь делать свою собственную вещь независимо (согласно ответу ниже), есть ли более умное решение, чем я, просто ожидая, что очередь закончит свою работу

Поскольку это скорее вопрос дизайна, чем конкретный кодовый вопрос, я ищу предложения по подходу к решению моей проблемы, советы о том, как я должен проектировать эту систему, но я определенно приветствую вас и хотел бы увидеть, код для поддержки предложений:) Я также приветствую любую критику в отношении файла Queue.js, который я связал с выше, и/или мое описание моей проблемы и подход, который я планирую предпринять, чтобы решить эту проблему.

Спасибо, Христо

4 ответа

Я бы предложил использовать http://headjs.com/ Он позволяет загружать js файлы параллельно, но выполнять их последовательно, по сути, то же самое, что вы хотите делать. Это довольно мало, и вы всегда можете использовать его для вдохновения.

Я бы также упомянул, что обработчики, которые полагаются на порядок выполнения, не являются хорошим дизайном. Я всегда могу разместить весь свой код начальной загрузки в готовом обработчике событий. Бывают случаи, когда вам нужно будет использовать обработчик нагрузки, если вам нужен доступ к изображениям, но для меня это не очень часто.


Вот что-то, что может сработать, это то, что вам нужно?

var q = (function(){
 var queue = [];
 var enqueue = function(fnc){
 if(typeof fnc === "function"){
 queue.push(fnc);
 }
 };
 var executeAll = function(){
 var someVariable = "Inside the Queue";
 while(queue.length>0){
 queue.shift()();
 }
 };
 return {
 enqueue:enqueue,
 executeAll:executeAll 
 };
}());
var someVariable = "Outside!"
q.enqueue(function(){alert("hi");});
q.enqueue(function(){alert(someVariable);});
q.enqueue(function(){alert("bye");});
alert("test");
q.executeAll();

alert("test"); выполняется перед тем, что вы положили в очередь.


как сохранить куски кода в очереди и выполнить его позже

Ваша текущая реализация уже работает для этого. В JavaScript нет объявленных типов, поэтому ваша очередь может содержать что угодно, включая объекты функции:

queue.enqueue(myfunc);
var f = queue.dequeue();
f();

как я могу сделать Очередь самостоятельно,

JavaScript, по сути, однопоточный, что означает, что только одно может выполняться в любой момент времени. Таким образом, очередь не может работать "независимо" от остальной части вашего кода, если это то, что вы имеете в виду.

У вас в основном есть два варианта:

  • Запускать все очереди в очереди один за другим - это даже не требует очереди, поскольку это то же самое, что просто поместить вызовы функций непосредственно в ваш код.

  • Использовать синхронизированные события: запускать одну функцию за раз и после ее завершения установить тайм-аут для выполнения следующей функции в очереди через определенный интервал. Приведем пример этого.

function run() {
 var func = this.dequeue();
 func();
 var self = this;
 setTimeout(function() { self.run(); }, 1000);
}

Если func является асинхронным запросом, вам нужно переместить setTimeout в функцию обратного вызова.


**The main functions**
**From there we can define the main elements required:**
var q=[];//our queue container
var paused=false; // a boolean flag
function queue() {}
function dequeue() {}
function next() {}
function flush() {}
function clear() {}
**you may also want to 'pause' the queue. We will therefore use a boolean flag too. 
Now let see the implementation, this is going to be very straightforward:**
var q = [];
var paused = false;
function queue() {
 for(var i=0;i< arguments.length;i++)
 q.push(arguments[i]);
}
function dequeue() {
 if(!empty()) q.pop();
}
function next() {
 if(empty()) return; //check that we have something in the queue
 paused=false; //if we call the next function, set to false the paused
 q.shift()(); // the same as var func = q.shift(); func();
}
function flush () {
 paused=false;
 while(!empty()) next(); //call all stored elements
}
function empty() { //helper function
 if(q.length==0) return true;
 return false;
}
function clear() {
 q=[];
}
**And here we have our basic queue system!
let see how we can use it:**
queue(function() { alert(1)},function(){ alert(2)},function(){alert(3)});
next(); // alert 1
dequeue(); // the last function, alerting 3 is removed
flush(); // call everything, here alert 2
clear(); // the queue is already empty in that case but anyway...

licensed under cc by-sa 3.0 with attribution.