Creating Sequential Tasks Using Promises

Is pretty simple. The target is to have a pre-start queue and a promise train that gets extended while new tasks are added.

The following code is an example.

class CompleteReadyStateTasks {
	constructor() {
		if (CompleteReadyStateTasks._instance)
			throw new Error("Multiple instantiation not allowed.");

		this.tasks = [];
		this.taskTrain = Promise.resolve();

		if (document.readyState !== 'complete') {
			document.addEventListener('readystatechange', event => {
				if (event.target.readyState === 'complete')
					this._executePendingTasks();
			});
		}

		CompleteReadyStateTasks._instance = this;
	}

	static getInstance() {
		if (!CompleteReadyStateTasks._instance)
			new CompleteReadyStateTasks();

		return CompleteReadyStateTasks._instance;
	}

	_executePendingTasks() {
		let task;

		while (task = this.tasks.shift()) {
			const _task = task;
			const method = () => new Promise(resolve =>
				requestAnimationFrame(async () => {
					await _task();
					resolve();
				})
			);
			this.taskTrain = this.taskTrain.then(method);
		}
	}

	_executePendingTasksIfStateComplete() {
		if (document.readyState === 'complete')
			this._executePendingTasks();
	}

	prependTask(task) {
		this.tasks.unshift(task);
		this._executePendingTasksIfStateComplete();
	}

	appendTask(task) {
		this.tasks.push(task);
		this._executePendingTasksIfStateComplete();
	}
}

CompleteReadyStateTasks.getInstance().prependTask(() =>
		document.getElementsByTagName('body')[0].classList.remove('hidden'));

CompleteReadyStateTasks.getInstance().appendTask(function() {
	var d = document, s = d.createElement('script');
	s.src = '//konsolebox.disqus.com/embed.js';
	s.setAttribute('data-timestamp', +new Date());
	(d.head || d.body).appendChild(s);
});
Back to top