One way is to treat the array data as a queue that is being consumed from another function. The function checks if the queue is empty (in which case it ends) and otherwise removes the last element, processes it, and executes again with the remaining elements.
var data = [
'e48c56b4-aebb-4499-a7c5-64db40381183',
'eb1cf18c-fbdb-4b0f-b775-34e4542a8675',
'62afe7bd-2061-4121-ab50-0b181e00e85a',
'943f1ae4-60cd-424d-94d2-7e3f66a88e1e',
'e6140cb0-b9c9-488a-8469-f9c3a51faffd',
'9c6b24e8-1b53-4d68-be98-672b74380491',
'f160a7d7-7609-44c9-9839-17ebd491ea21'
];
function sleep(f, m) {
setTimeout(() => {
f();
}, m)
}
function procesar_y_eliminar() {
if(data.length===0) {
return;
}
var registro=data.pop();
var elemento=jQuery('<span class="pull-right label label-success">LEÍDO</span><br/>');
$('.super').append(registro).append(elemento);
sleep(() => {
elemento.removeClass('label-success');
elemento.addClass('label-warning');
elemento.html('PROCESADO');
}, 2000);
sleep(() => {
elemento.removeClass('label-warning');
elemento.addClass('label-danger');
elemento.html('ELIMINADO');
}, 4000);
sleep(()=> {
procesar_y_eliminar();
},5000);
}
procesar_y_eliminar();
.super {
width: auto;
height: 150px;
border: 1px solid black;
padding: 5px 5px 5px 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<br />
<br />
<br />
<div class='container'>
<div class='super'></div>
</div>
This same behavior could be shown a bit more intuitively if the sleep function returned a promise, such that we could do then
on its output. It's like intuitive to use then
to indicate that one thing happens after another.
This is the same example but promisificating the sleep. Note that now the contents of procesar_y_eliminar
are not two sleep with different intervals, but one followed by the other by then
. This would allow to execute not only two but N steps on each object without generating more nesting or having to calculate the interval for each one.
var data = [
'e48c56b4-aebb-4499-a7c5-64db40381183',
'eb1cf18c-fbdb-4b0f-b775-34e4542a8675',
'62afe7bd-2061-4121-ab50-0b181e00e85a',
'943f1ae4-60cd-424d-94d2-7e3f66a88e1e',
'e6140cb0-b9c9-488a-8469-f9c3a51faffd',
'9c6b24e8-1b53-4d68-be98-672b74380491',
'f160a7d7-7609-44c9-9839-17ebd491ea21'
];
function sleep(m) {
return new Promise((resolve, reject) => {
setTimeout(resolve, m)
});
}
function procesar_y_eliminar() {
if (data.length === 0) {
return;
}
var registro = data.pop();
var elemento = $('<span class="pull-right label label-success">LEÍDO</span><br/>');
$('.super')
.append(registro)
.append(elemento);
return sleep(2000)
.then(() => {
elemento
.removeClass('label-success')
.addClass('label-warning')
.html('PROCESADO');
return sleep(2000);
}).then(() => {
elemento
.removeClass('label-warning')
.addClass('label-danger')
.html('ELIMINADO');
return sleep(2000);
}).then(() => {
return procesar_y_eliminar();
});
}
procesar_y_eliminar();
.super {
width: auto;
height: 150px;
border: 1px solid black;
padding: 5px 5px 5px 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<br />
<br />
<br />
<div class='container'>
<div class='super'></div>
</div>
There are more elaborate ways (although not necessarily better ones). I've taken over the bluebird library (faster and more versatile than the native promises), which has the Promise.map which allows you to execute promises with a certain concurrency index. You can run one, two, etc., all at the same time.
I think in this case using promises arrays is unnecessary and would serve only as a proof of concept. Actually the most efficient thing would be to look for a queue library like queue or d3-queue that are specifically for this use case.