JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/client/seriallency.min.js"></script>
<p>
Click on users to queue a 2 seconds promise. Try to clic as fast you can :)
</p>
<div class="graph">
<div class="user" id="user1">
<div class="name">
User 1
</div>
</div>
<div class="user" id="user2">
<div class="name">
User 2
</div>
</div>
<div class="user" id="user3">
<div class="name">
User 3
</div>
</div>
</div>
<h3>
Seriallency state:
</h3>
<div>
getQuantityProcessing(): <span id="getQuantityProcessing"></span>
</div>
<div>
getQueueSize(): <span id="getQueueSize"></span>
</div>
<div>
getQueueSize('user1'): <span id="getQueueSize_user1"></span>
</div>
<div>
getQueueSize('user2'): <span id="getQueueSize_user2"></span>
</div>
<div>
getQueueSize('user3'): <span id="getQueueSize_user3"></span>
</div>
CSS
.user {
height: auto;
border-top: 1px solid gray;
user-select: none;
}
.user:last-child {
border-bottom: 1px solid gray;
}
.user:after {
display: table;
content: '';
clear: both;
}
.user .name {
float: left;
height: 20px;
width: 60px;
background-color: lightgray;
padding: 10px 10px;
cursor: pointer;
text-align: center;
}
.user .name:hover{
background-color: aliceblue;
}
.promise {
width: 50px;
height: 20px;
float: left;
margin-left: 5px;
margin-top: 10px;
text-align: center;
position: relative;
overflow: hidden;
}
.promise:before{
content: '';
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 0%;
background-color: lightgreen;
opacity: .5;
}
.promise.pending {
background-color: yellow;
}
.promise.pending:before{
transition: width 2s linear;
width: 100%;
}
.promise.done {
background-color: lightgreen;
}
.promise.queued {
background-color: lightblue;
}
JavaScript
var seriallency = new Seriallency();
var users = [
{
id: 'user1',
processes: 0
},
{
id: 'user2',
processes: 0
},
{
id: 'user3',
processes: 0
}
];
seriallency.on('resolved', refreshSeriallencyStatus);
refreshSeriallencyStatus();
$('.graph').on('click', '.user .name', function (event){
var userId = $(this).closest('.user').attr('id');
queueProcess(userId);
})
function queueProcess(userId){
var counter;
var user = users.find(function(user){ return user.id === userId; });
user.processes += 1;
createUserStep(user.id, user.processes, 'queued');
setTimeout(function (){
// this timeout is only to allow css transition to start with loadbar empty
seriallency.push({
serializeBy: user.id,
fn: someProcess,
params:[user.id, user.processes]
});
refreshSeriallencyStatus();
}, 1);
}
function someProcess(user, step){
setUserStepStatus(user, step, 'pending');
refreshSeriallencyStatus();
return new Promise(function (resolve, reject){
setTimeout(function (){
setUserStepStatus(user, step, 'done');
resolve();
}, 2000);
});
}
function createUserStep(user, step, initialStatus){
var $promise = $('<div></div>', {
id: user + '_step' + step,
class:'promise ' + initialStatus,
text: 'p.' + step
});
$('#' + user).append($promise);
}
function setUserStepStatus(user, step, status){
$('#' + user + '_step' + step).removeClass('pending done queued').addClass(status);
}
function refreshSeriallencyStatus(){ $('#getQuantityProcessing').text(seriallency.getQuantityProcessing());
$('#getQueueSize').text(seriallency.getQueueSize());
$('#getQueueSize_user1').text(seriallency.getQueueSize('user1'));
$('#getQueueSize_user2').text(seriallency.getQueueSize('user2'));
$('#getQueueSize_user3').text(seriallency.getQueueSize('user3'));
}