Java Script dengan sifatnya single thread, asynchronous, dan non blocking tentu tidak seperti pada bahasa pemrograman umumnya yaitu eksekusi akan dilakukan satu-persatu/demi baris tanpa bisa loncat sebelum eksekusi sebelumnya selesai. Biasanya pada bahasa pemrograman umum menggunakan teknik threading. Pada java script misalkan komunikasi berbasis AJAX akan sangat efektif untuk loading beragam data ke sisi klien sehingga aplikasi sangat responsif.
Java Script unggul untuk hal demikian dan cocok untuk server dengan adanya node.js akan tetapi terkadang kita butuh yang namanya operasi matematika yang intensif seperti operasi pada looping. Kita tidak bisa membuat menampilkan animasi spinner yang melibatkan looping secara intensitf. Akibatnya animasi spinner malahan tidak muncul.
Operasi looping yang intensif biasanya menggunakan teknik time.sleep() agar responsif sehingga setiap perubahan componen HTML dapat dilakukan dengan mudah. Sebagai contoh kita tidak akan bisa mengubah component HTML berikut pada saat looping berlangsung
<label id="counter"></label>
didalam looping
for (let i=0;i<100;i++){ console.log(i); $('#counter').text(i); }
Bahkan kalaupun menggunakan teknik setTimeout() pun tidak akan bisa
for (let i=0;i<100;i++){ console.log(i); setTimeout(function(){},100); $('#counter').text(i); }
Time Sleep
Penggunaan looping sebaiknya dihindari tapi terkadang hal itu tidak memungkinkan sehingga di bahasa pemrograman lain didapatkan feature time.sleep() untuk memberikan ruang/jeda waktu agar operasi yang lainnya bisa berjalan sambil proses yang sedang dikerjakan berjalan. Sayangnya time.sleep() pada java script itu tidak ada! karena sifat nya yang asynchronous
Await, async, dan Promise
Salah satunya yaitu kita akan membuat function dengan async. Perhatikan button click dibawah ini yang diberikan tambahan async
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } //https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep $('#btn').click( async function(){ for (let i=0;i<100;i++){ console.log(i); await sleep(0.1); $('#counter').text(i+1); } });
Dengan cara diatas maka component HTML bisa kita ubah selama proses looping berjalan! Berikut kode lengkapnya
<html lang="en"> <head> <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-3.6.0.js"></script> <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script> </head> <body> <label id="counter">mulai...</label><br> <button id="btn" type="button">OK</button> </body> <script> function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } //https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep $('#btn').click( async function(){ for (let i=0;i<100;i++){ console.log(i); //setTimeout(function(){},1000); await sleep(0.1); $('#counter').text(i+1); } }); </script> </html>
Spinner berbasis CSS dan JS
Memastikan bahwa aplikasi berjalan dengan baik maka dibutuhkan animasi yang bagus sebisa mungkin tidak perlu menggunakan gambar GiF tapi cukup hanya CSS dan JS saja, kalian bisa peroleh di https://spin.js.org
Atau kalian bisa download spin.js dan spin.css berikut ini spin.js dan spin.css Misalkan kita tambahkan component dan pengaturan sebagai berikut
pengaturan CSS
<style> .centered { position: fixed; /* or absolute */ top: 50%; left: 50%; } </style>
Component HTML
<div id="spinner" class = "centered"></div>
Pengaturan Spinner
var opts = { lines: 13, // The number of lines to draw length: 38, // The length of each line width: 17, // The line thickness radius: 45, // The radius of the inner circle scale: 1, // Scales overall size of the spinner corners: 1, // Corner roundness (0..1) speed: 1, // Rounds per second rotate: 0, // The rotation offset animation: 'spinner-line-fade-quick', // The CSS animation name for the lines direction: 1, // 1: clockwise, -1: counterclockwise color: '#FAECD6', // CSS color or array of colors fadeColor: 'transparent', // CSS color or array of colors top: '50%', // Top position relative to parent left: '50%', // Left position relative to parent shadow: '0 0 1px transparent', // Box-shadow for the lines zIndex: 2000000000, // The z-index (defaults to 2e9) className: 'spinner', // The CSS class to assign to the spinner position: 'absolute', // Element positioning };
Penggunaan Spinner didalam Looping
$('#btn').click( async function(){ let target = document.getElementById('spinner'); let spinner = new Spinner(opts).spin(target); for (let i=0;i<100;i++){ console.log(i); //setTimeout(function(){},1000); await sleep(0.1); $('#counter').text(i+1); } spinner.stop(); });
Bila masih bingung, berikut kode lengkapnya
<html lang="en"> <head> <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-3.6.0.js"></script> <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script> <!-- spin --> <link rel="stylesheet" href="spin/spin.css" /> <script src="spin/spin.js"></script> <style> .centered { position: fixed; /* or absolute */ top: 50%; left: 50%; } </style> </head> <body> <label id="counter">mulai...</label><br> <div id="spinner" class = "centered"></div> <button id="btn" type="button">OK</button> </body> <script> var opts = { lines: 13, // The number of lines to draw length: 38, // The length of each line width: 17, // The line thickness radius: 45, // The radius of the inner circle scale: 1, // Scales overall size of the spinner corners: 1, // Corner roundness (0..1) speed: 1, // Rounds per second rotate: 0, // The rotation offset animation: 'spinner-line-fade-quick', // The CSS animation name for the lines direction: 1, // 1: clockwise, -1: counterclockwise color: '#FAECD6', // CSS color or array of colors fadeColor: 'transparent', // CSS color or array of colors top: '50%', // Top position relative to parent left: '50%', // Left position relative to parent shadow: '0 0 1px transparent', // Box-shadow for the lines zIndex: 2000000000, // The z-index (defaults to 2e9) className: 'spinner', // The CSS class to assign to the spinner position: 'absolute', // Element positioning }; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } //https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep $('#btn').click( async function(){ let target = document.getElementById('spinner'); let spinner = new Spinner(opts).spin(target); for (let i=0;i<100;i++){ console.log(i); //setTimeout(function(){},1000); await sleep(0.1); $('#counter').text(i+1); } spinner.stop(); }); </script> </html>
ref: https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep