Jika saya perlu memanggil fungsi ini satu demi satu,
$('#art1').animate({'width':'1000px'},1000);
$('#art2').animate({'width':'1000px'},1000);
$('#art3').animate({'width':'1000px'},1000);
Saya tahu di jQuery saya bisa melakukan sesuatu seperti:
$('#art1').animate({'width':'1000px'},1000,'linear',function(){
$('#art2').animate({'width':'1000px'},1000,'linear',function(){
$('#art3').animate({'width':'1000px'},1000);
});
});
Tapi, mari kita asumsikan bahwa saya tidak menggunakan jQuery dan saya ingin menelepon:
some_3secs_function(some_value);
some_5secs_function(some_value);
some_8secs_function(some_value);
Bagaimana saya harus memanggil fungsi ini untuk mengeksekusi some_3secs_function
, dan SETELAH panggilan itu berakhir, kemudian jalankan some_5secs_function
dan SETELAH panggilan itu berakhir, kemudian panggil some_8secs_function
?
MEMPERBARUI:
Ini masih tidak berfungsi:
(function(callback){
$('#art1').animate({'width':'1000px'},1000);
callback();
})((function(callback2){
$('#art2').animate({'width':'1000px'},1000);
callback2();
})(function(){
$('#art3').animate({'width':'1000px'},1000);
}));
Tiga animasi dimulai pada waktu yang bersamaan
Di mana kesalahan saya?
Jawaban:
Di Javascript, ada yang sinkron dan asinkron fungsi .
Fungsi Sinkron
Sebagian besar fungsi dalam Javascript bersifat sinkron. Jika Anda memanggil beberapa fungsi sinkron berturut-turut
mereka akan mengeksekusi secara berurutan.
doSomethingElse
tidak akan mulai sampaidoSomething
selesai.doSomethingUsefulThisTime
, pada gilirannya, tidak akan mulai sampaidoSomethingElse
selesai.Fungsi Asinkron
Fungsi asinkron, bagaimanapun, tidak akan menunggu satu sama lain. Mari kita lihat contoh kode yang sama dengan yang kita miliki di atas, kali ini dengan asumsi bahwa fungsinya tidak sinkron
Fungsi-fungsi akan diinisialisasi secara berurutan, tetapi semuanya akan dieksekusi secara kasar pada saat yang sama. Anda tidak dapat secara konsisten memprediksi yang mana yang akan selesai lebih dulu: yang terjadi untuk mengambil jumlah waktu terpendek untuk mengeksekusi akan selesai terlebih dahulu.
Tetapi kadang-kadang, Anda ingin menjalankan fungsi yang tidak sinkron secara berurutan, dan kadang-kadang Anda ingin fungsi yang sinkron dijalankan secara tidak sinkron. Untungnya, ini dimungkinkan dengan callback dan timeout, masing-masing.
Telepon balik
Mari kita asumsikan bahwa kita memiliki tiga fungsi asynchronous bahwa kita ingin mengeksekusi dalam rangka,
some_3secs_function
,some_5secs_function
, dansome_8secs_function
.Karena fungsi dapat diteruskan sebagai argumen dalam Javascript, Anda bisa meneruskan fungsi sebagai panggilan balik untuk dieksekusi setelah fungsi selesai.
Jika kita membuat fungsi seperti ini
maka Anda dapat menghubungi secara berurutan, seperti ini:
Batas waktu
Di Javascript, Anda bisa memberi tahu fungsi untuk dijalankan setelah batas waktu tertentu (dalam milidetik). Ini dapat, pada dasarnya, membuat fungsi sinkron berperilaku tidak sinkron.
Jika kita memiliki tiga fungsi sinkron, kita dapat menjalankannya secara tidak sinkron menggunakan
setTimeout
fungsi tersebut.Namun, ini agak jelek dan melanggar prinsip KERING [wikipedia] . Kita bisa membersihkan ini sedikit dengan membuat fungsi yang menerima larik fungsi dan batas waktu.
Ini bisa disebut seperti ini:
Singkatnya, jika Anda memiliki fungsi asinkron yang ingin Anda jalankan secara sinkron, gunakan panggilan balik, dan jika Anda memiliki fungsi sinkron yang ingin Anda jalankan secara tidak sinkron, gunakan timeout.
sumber
Jawaban ini menggunakan
promises
, fitur JavaScriptECMAScript 6
standar. Jika platform target Anda tidak mendukungpromises
, isi dengan PromiseJs .Lihat jawaban saya di sini. Tunggu hingga Fungsi dengan animasi selesai hingga menjalankan Fungsi lainnya jika Anda ingin menggunakan
jQuery
animasi.Inilah kode Anda akan terlihat dengan
ES6 Promises
danjQuery animations
.Metode normal juga dapat dibungkus
Promises
.The
then
Metode dijalankan segera setelahPromise
selesai. Biasanya, nilai pengembalian yangfunction
diteruskan kethen
diteruskan ke yang berikutnya sebagai hasilnya.Tetapi jika a
Promise
dikembalikan,then
fungsi berikutnya menunggu sampaiPromise
selesai dieksekusi dan menerima hasilnya (nilai yang diteruskan kefulfill
).sumber
Sepertinya Anda tidak sepenuhnya menghargai perbedaan antara eksekusi fungsi sinkron dan asinkron .
Kode yang Anda berikan dalam pembaruan Anda segera menjalankan setiap fungsi panggilan balik Anda, yang pada gilirannya segera memulai animasi. Animasi, bagaimanapun, mengeksekusi asyncronously . Ini berfungsi seperti ini:
setTimeout
dengan fungsi yang berisi langkah animasi berikutnya dan penundaansetTimeout
dieksekusiIni berlanjut sampai langkah terakhir dalam animasi selesai. Sementara itu, fungsi sinkron Anda sudah lama diselesaikan. Dengan kata lain, panggilan Anda ke
animate
fungsi tidak benar - benar membutuhkan waktu 3 detik. Efeknya disimulasikan dengan penundaan dan panggilan balik.Yang Anda butuhkan adalah antrian . Secara internal, jQuery antrian animasi, hanya mengeksekusi Anda panggilan balik setelah animasi yang sesuai selesai. Jika panggilan balik Anda kemudian memulai animasi lain, efeknya adalah mereka dieksekusi secara berurutan.
Dalam kasus paling sederhana ini setara dengan yang berikut:
Berikut adalah fungsi perulangan asinkron umum. Ini akan memanggil fungsi yang diberikan secara berurutan, menunggu jumlah detik yang ditentukan antara masing-masing.
Pemakaian:
Anda jelas dapat memodifikasi ini untuk mengambil waktu tunggu yang dapat dikonfigurasi atau untuk segera menjalankan fungsi pertama atau untuk berhenti mengeksekusi ketika fungsi dalam rantai kembali
false
atau keapply
fungsi dalam konteks tertentu atau apa pun yang Anda butuhkan.sumber
Saya percaya perpustakaan async akan memberi Anda cara yang sangat elegan untuk melakukan ini. Sementara janji dan panggilan balik bisa sedikit sulit untuk ditangani, async dapat memberikan pola yang rapi untuk merampingkan proses pemikiran Anda. Untuk menjalankan fungsi secara serial, Anda harus meletakkannya di air terjun async . Dalam async lingo, setiap fungsi disebut a
task
yang mengambil beberapa argumen dan acallback
; yang merupakan fungsi selanjutnya dalam urutan. Struktur dasar akan terlihat seperti:Saya baru saja mencoba menjelaskan struktur secara singkat di sini. Bacalah panduan air terjun untuk informasi lebih lanjut, ini ditulis dengan cukup baik.
sumber
fungsi Anda harus menggunakan fungsi panggilan balik, yang dipanggil saat selesai.
maka penggunaannya akan seperti:
sumber
Saya tidak akan membahas diskusi mendalam tentang setTimeout di sini, tetapi:
sumber
Karena Anda menandai dengan javascript, saya akan pergi dengan kontrol timer karena nama fungsi Anda adalah 3, 5, dan 8 detik. Jadi mulai timer Anda, 3 detik masuk, panggilan pertama, 5 detik panggilan kedua, 8 detik panggilan ketiga, lalu setelah selesai, hentikan timer.
Biasanya dalam Javascript apa yang Anda miliki benar untuk fungsi berjalan satu demi satu, tetapi karena sepertinya Anda mencoba melakukan animasi waktunya, timer akan menjadi taruhan terbaik Anda.
sumber
sumber
next
lakukan?Anda juga bisa menggunakan janji dengan cara ini:
Anda harus membuat
some_value
global untuk mengaksesnya dari dalam. MakaAtau, dari fungsi luar Anda bisa mengembalikan nilai yang akan digunakan fungsi dalam, seperti:
sumber
Saya menggunakan fungsi 'waitUntil' berdasarkan setTimeout javascript
Ini akan bekerja dengan sempurna jika fungsi Anda menetapkan kondisi tertentu menjadi true, yang dapat Anda polling. Ditambah lagi dengan timeout, yang menawarkan Anda alternatif jika fungsi Anda gagal melakukan sesuatu (bahkan dalam rentang waktu. Pikirkan tentang umpan balik pengguna!)
misalnya
sumber
Jika metode 1 harus dijalankan setelah metode 2, 3, 4. Cuplikan kode berikut dapat menjadi solusi untuk ini menggunakan objek Ditangguhkan dalam JavaScript.
sumber