Jalankan skrip setelah penundaan tertentu menggunakan JavaScript

189

Apakah ada metode JavaScript yang mirip dengan jQuery delay()atau wait()(untuk menunda eksekusi skrip untuk jangka waktu tertentu)?

Niyaz
sumber

Jawaban:

189

Ada yang berikut ini:

setTimeout(function, milliseconds);

fungsi yang dapat dilewati waktu setelah fungsi akan dieksekusi.

Lihat: Metode JendelasetTimeout() .

Abhinav
sumber
3
Itu bukan ekspresi yang dieksekusi itu fungsi. Jawaban @Marius menggambarkan hal itu.
pedrofurla
117
ini bukan penundaan, itu garpu. Keterlambatan harus bekerja di utas yang sama.
DragonLord
13
Ini akan segera menjalankan function_reference. Untuk "bekerja" (asinkron) itu harus dinyatakan sebagai: setTimeout (function () {MethodToCall ();}, 1000);
Bernoulli IT
6
Saya ingin menunjukkan bahwa kita berbicara tentang JavaScript; memunculkan "utas" atau harus berfungsi "serempak" mungkin benar secara teknis dan semantik tetapi tidak benar-benar cocok dalam konteks JavaScript, mengingat benar-benar tidak ada cara untuk mencapai penundaan dengan salah satu metode tersebut (Anda tidak perlu t buat "utas" di JS seperti yang Anda lakukan dalam bahasa lain). Juga, ini tidak akan segera dijalankan function_referencekecuali jika Anda menyertakan (). Yaitu function_referencehanya itu - referensi; lewat function_reference()akan segera memanggil fungsi.
Danny Bullis
237

Hanya untuk menambahkan apa yang dikatakan orang lain tentang setTimeout: Jika Anda ingin memanggil fungsi dengan parameter di masa depan, Anda perlu mengatur beberapa panggilan fungsi anonim.

Anda harus melewati fungsi sebagai argumen untuk dipanggil nanti. Akibatnya ini berarti tanpa tanda kurung di belakang nama. Berikut ini akan memanggil lansiran sekaligus, dan itu akan menampilkan 'Halo dunia':

var a = "world";
setTimeout(alert("Hello " + a), 2000);

Untuk memperbaikinya, Anda dapat meletakkan nama fungsi (seperti yang dilakukan Flubba) atau Anda dapat menggunakan fungsi anonim. Jika Anda harus melewati parameter, maka Anda harus menggunakan fungsi anonim.

var a = "world";
setTimeout(function(){alert("Hello " + a)}, 2000);
a = "Stack Overflow";

Tetapi jika Anda menjalankan kode itu, Anda akan melihat bahwa setelah 2 detik popup akan mengatakan 'Hello Stack Overflow'. Ini karena nilai variabel a telah berubah dalam dua detik tersebut. Untuk membuatnya mengatakan 'Halo dunia' setelah dua detik, Anda perlu menggunakan cuplikan kode berikut:

function callback(a){
    return function(){
        alert("Hello " + a);
    }
}
var a = "world";
setTimeout(callback(a), 2000);
a = "Stack Overflow";

Ini akan menunggu 2 detik dan kemudian muncul 'Hello world'.

Marius
sumber
37

Hanya untuk sedikit memperluas ... Anda dapat mengeksekusi kode secara langsung dalam setTimeoutpanggilan, tetapi seperti yang dikatakan @patrick , Anda biasanya menetapkan fungsi panggilan balik, seperti ini. Waktunya milidetik

setTimeout(func, 4000);
function func() {
    alert('Do stuff here');
}
Polsonby
sumber
27

Jika Anda benar-benar ingin memiliki fungsi pemblokiran (sinkron) delay(untuk apa pun), mengapa tidak melakukan sesuatu seperti ini:

<script type="text/javascript">
    function delay(ms) {
        var cur_d = new Date();
        var cur_ticks = cur_d.getTime();
        var ms_passed = 0;
        while(ms_passed < ms) {
            var d = new Date();  // Possible memory leak?
            var ticks = d.getTime();
            ms_passed = ticks - cur_ticks;
            // d = null;  // Prevent memory leak?
        }
    }

    alert("2 sec delay")
    delay(2000);
    alert("done ... 500 ms delay")
    delay(500);
    alert("done");
</script>
Mario Werner
sumber
2
Kesulitan dengan solusi ini adalah bahwa ia secara aktif menggunakan prosesor, yang mengarah pada peningkatan penggunaan daya dan berkurangnya sumber daya yang tersedia untuk utas / proses lainnya (misalnya tab lain, program lain). Sleep, sebaliknya, untuk sementara menunda penggunaan sumber daya sistem thread.
ramcdougal
1
lebih baik menggunakan Date.now () daripada Date () baru dan jangan berpikir tentang kebocoran memori
WayFarer
1
Tentu saja ini adalah CPU intensif, tetapi untuk pengujian cepat dan kotor berfungsi
Maris B.
Saya ingin versi yang tidak mengunci utas, jadi saya dapat menyegarkan DOM sebelum delay(untuk menjawab pertanyaan ini ). Apakah ada cara untuk melakukannya?
Gui Imamura 615
3
Rutin yang lebih ringkas: fungsi delay (ms) {var start_time = Date.now (); while (Date.now () - start_time <ms); }
Duke
15

Anda perlu menggunakan setTimeout dan memberikannya fungsi panggilan balik. Alasan Anda tidak dapat menggunakan sleep dalam javascript adalah karena Anda akan memblokir seluruh halaman dari melakukan sesuatu sementara itu. Bukan rencana yang bagus. Gunakan model acara Javascript dan tetap senang. Jangan melawannya!

Patrick
sumber
2
Tetap akan bermanfaat untuk tujuan pengujian. Seperti menunda pengiriman formulir selama beberapa detik untuk mengevaluasi perubahan halaman sebelum permintaan HTTP baru dibuat.
bergegas
1
@rushinge kemudian atur panggilan balik untuk mengirim formulir dan menonaktifkan kirim formulir default
Populus
1
Gagasan buruk untuk meninggalkan tautan sebagai kode ... karena sekarang tidak berfungsi.
Emmet Arries
1
Atau Anda tahu, saya bisa memperbaikinya.
Patrick
14

Anda juga dapat menggunakan window.setInterval () untuk menjalankan beberapa kode berulang kali pada interval reguler.

rcoup
sumber
2
setInterval () tidak boleh digunakan sebagai gantinya harus menggunakan setTimeout
paul
9
setTimeout()lakukan sekali, setInterval()lakukan berulang kali. Jika Anda ingin kode Anda berjalan setiap 5 detik, setInterval()dibuat untuk pekerjaan itu.
rcoup
11

Untuk menambahkan komentar sebelumnya, saya ingin mengatakan yang berikut:

The setTimeout()fungsi dalam JavaScript tidak berhenti eksekusi script per se, tetapi hanya memberitahu compiler untuk menjalankan suatu kode di masa depan.

Tidak ada fungsi yang benar-benar dapat menghentikan sementara eksekusi ke dalam JavaScript. Namun, Anda dapat menulis fungsi Anda sendiri yang melakukan sesuatu seperti loop tanpa syarat hingga waktu tercapai dengan menggunakan Date()fungsi dan menambahkan interval waktu yang Anda butuhkan.

narasi
sumber
11

Jika Anda hanya perlu menguji penundaan, Anda dapat menggunakan ini:

function delay(ms) {
   ms += new Date().getTime();
   while (new Date() < ms){}
}

Dan kemudian jika Anda ingin menunda selama 2 detik Anda lakukan:

delay(2000);

Mungkin bukan yang terbaik untuk produksi. Lebih lanjut tentang itu di komentar

Christoffer
sumber
@ U2744 SNOWFLAKE Dapatkah Anda mencoba dan sedikit lebih tepat dalam komentar Anda
Christoffer
1
Ya, ini adalah loop sibuk yang akan menguras baterai laptop dan perangkat seluler lainnya, dan mungkin juga mencegah UI merespons (atau bahkan menampilkan).
Ry-
@ U2744SNOWFLAKE Masuk akal. Telah memperbarui jawabannya, untuk apa saya menggunakan fungsi ini :)
Christoffer
2
Bekerja cukup baik dalam pengembangan untuk solusi cepat & kotor (dan sementara).
HumanInDisguise
5

mengapa Anda tidak bisa meletakkan kode di belakang janji? (diketik di bagian atas kepala saya)

new Promise(function(resolve, reject) {
  setTimeout(resolve, 2000);
}).then(function() {
  console.log('do whatever you wanted to hold off on');
});

Al Joslin
sumber
5

Jawaban sederhana adalah:

setTimeout(
    function () {
        x = 1;
    }, 1000);

Fungsi di atas menunggu 1 detik (1000 ms) kemudian menetapkan x ke 1. Jelas ini adalah contoh; Anda dapat melakukan apa pun yang Anda inginkan di dalam fungsi anonim.

Luca
sumber
4

Saya benar-benar menyukai penjelasan Maurius (respons terunggul tertinggi) dengan tiga metode berbeda untuk menelepon setTimeout.

Dalam kode saya, saya ingin secara otomatis menavigasi ke halaman sebelumnya setelah menyelesaikan acara penyimpanan AJAX. Penyelesaian acara simpan memiliki sedikit animasi di CSS yang menunjukkan bahwa penyimpanan berhasil.

Dalam kode saya, saya menemukan perbedaan antara dua contoh pertama:

setTimeout(window.history.back(), 3000);

Yang ini tidak menunggu batas waktu - bagian belakang () dipanggil segera tidak peduli berapa pun nomor yang saya tunda.

Namun, ubah ini menjadi:

setTimeout(function() {window.history.back()}, 3000);

Ini tepat seperti yang saya harapkan.

Ini tidak spesifik untuk operasi back (), sama terjadi dengan alert(). Pada dasarnya dengan yang alert()digunakan dalam kasus pertama, waktu tunda diabaikan. Ketika saya mengabaikan popup, animasi untuk CSS berlanjut.

Jadi, saya akan merekomendasikan metode kedua atau ketiga yang ia gambarkan bahkan jika Anda menggunakan fungsi bawaan dan tidak menggunakan argumen.

Doug
sumber
1

Saya punya beberapa perintah ajax yang ingin saya jalankan dengan penundaan di antaranya. Berikut adalah contoh sederhana dari satu cara untuk melakukan itu. Saya siap untuk dicabik-cabik karena pendekatan saya yang tidak konvensional. :)

//  Show current seconds and milliseconds
//  (I know there are other ways, I was aiming for minimal code
//  and fixed width.)
function secs()
{
    var s = Date.now() + ""; s = s.substr(s.length - 5);
  return s.substr(0, 2) + "." + s.substr(2);
}

//  Log we're loading
console.log("Loading: " + secs());

//  Create a list of commands to execute
var cmds = 
[
    function() { console.log("A: " + secs()); },
    function() { console.log("B: " + secs()); },
    function() { console.log("C: " + secs()); },
    function() { console.log("D: " + secs()); },
    function() { console.log("E: " + secs()); },
  function() { console.log("done: " + secs()); }
];

//  Run each command with a second delay in between
var ms = 1000;
cmds.forEach(function(cmd, i)
{
    setTimeout(cmd, ms * i);
});

// Log we've loaded (probably logged before first command)
console.log("Loaded: " + secs());

Anda dapat menyalin blok kode dan menempelkannya ke jendela konsol dan melihat sesuatu seperti:

Loading: 03.077
Loaded: 03.078
A: 03.079
B: 04.075
C: 05.075
D: 06.075
E: 07.076
done: 08.076
JohnnyIV
sumber
1

Solusi paling sederhana untuk memanggil fungsi Anda dengan penundaan adalah:

function executeWithDelay(anotherFunction) {
    setTimeout(anotherFunction, delayInMilliseconds);
}
Jackkobec
sumber
0

fungsi penundaan:

/**
 * delay or pause for some time
 * @param {number} t - time (ms)
 * @return {Promise<*>}
 */
const delay = async t => new Promise(resolve => setTimeout(resolve, t));

penggunaan di dalam asyncfungsi:

await delay(1000);
Zuhair Taha
sumber
-1

Seperti yang lain katakan, setTimeout adalah taruhan Anda yang paling aman.
Tetapi kadang-kadang Anda tidak dapat memisahkan logika dengan fungsi baru maka Anda dapat menggunakan Date.now () untuk mendapatkan milidetik dan melakukan penundaan sendiri ....

function delay(milisecondDelay) {
   milisecondDelay += Date.now();
   while(Date.now() < milisecondDelay){}
}

alert('Ill be back in 5 sec after you click OK....');
delay(5000);
alert('# Im back # date:' +new Date());

JavaSheriff
sumber