เรียกใช้งานสคริปต์หลังจากการหน่วงเวลาโดยใช้ JavaScript


189

มีวิธีการ JavaScript ใด ๆ ที่คล้ายกับ jQuery delay()หรือwait()(เพื่อชะลอการเรียกใช้สคริปต์ตามระยะเวลาที่กำหนด)

คำตอบ:


189

มีดังต่อไปนี้:

setTimeout(function, milliseconds);

ฟังก์ชั่นซึ่งสามารถผ่านเวลาหลังจากที่ฟังก์ชั่นจะถูกดำเนินการ

ดู: หน้าต่างsetTimeout()วิธี


3
ไม่ใช่นิพจน์ที่เรียกใช้งานเป็นฟังก์ชั่น คำตอบ @Marius แสดงให้เห็นว่า
pedrofurla

117
นี่ไม่ใช่ความล่าช้า แต่เป็นทางแยก ความล่าช้าควรทำงานในเธรดเดียวกัน
DragonLord

13
สิ่งนี้จะดำเนินการ function_reference ทันที หากต้องการ "งาน" (แบบอะซิงโครนัส) ควรระบุเป็น: setTimeout (function () {MethodToCall ();}, 1000);
Bernoulli IT

6
ฉันต้องการชี้ให้เห็นว่าเรากำลังพูดถึง JavaScript; นำขึ้น "หัวข้อ" หรือว่าควรจะทำงาน "พร้อมกัน" อาจเป็นจริงในทางเทคนิคและความหมายแต่ไม่เหมาะสมในบริบทของ JavaScript พิจารณาว่าไม่มีวิธีที่จะบรรลุความล่าช้าด้วยวิธีการอย่างใดอย่างหนึ่ง (คุณ don ' ไม่สร้าง "กระทู้" ใน JS เหมือนที่คุณทำในภาษาอื่น) นอกจากนี้สิ่งนี้จะไม่ดำเนินการทันทีfunction_referenceหากคุณ()ไม่มี คือfunction_referenceเป็นเพียงที่ - อ้างอิง; การส่งผ่านfunction_reference()จะเรียกใช้ฟังก์ชันทันที
Danny Bullis

237

เพียงเพิ่มสิ่งที่ทุกคนพูดถึงsetTimeout: หากคุณต้องการเรียกใช้ฟังก์ชันที่มีพารามิเตอร์ในอนาคตคุณต้องตั้งค่าการเรียกใช้ฟังก์ชันที่ไม่ระบุชื่อ

คุณต้องผ่านฟังก์ชั่นเป็นอาร์กิวเมนต์เพื่อให้เรียกใช้ในภายหลัง ในความหมายนี้หมายความว่าไม่มีเครื่องหมายวงเล็บอยู่ด้านหลังชื่อ ต่อไปนี้จะเรียกการแจ้งเตือนทันทีและจะแสดง 'Hello world':

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

ในการแก้ไขปัญหานี้คุณสามารถใส่ชื่อฟังก์ชั่น (ตามที่ Flubba ได้ทำไว้) หรือคุณสามารถใช้ฟังก์ชั่นที่ไม่ระบุชื่อก็ได้ หากคุณต้องการส่งผ่านพารามิเตอร์คุณต้องใช้ฟังก์ชันที่ไม่ระบุชื่อ

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

แต่ถ้าคุณเรียกใช้รหัสนั้นคุณจะสังเกตเห็นว่าหลังจาก 2 วินาทีป๊อปอัพจะพูดว่า 'Hello Stack Overflow' นี่เป็นเพราะค่าของตัวแปร a มีการเปลี่ยนแปลงในสองวินาทีนั้น หากต้องการให้มันพูดว่า 'Hello world' หลังจากสองวินาทีคุณจะต้องใช้ข้อมูลโค้ดต่อไปนี้:

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

จะรอประมาณ 2 วินาทีจากนั้นป๊อปอัป 'Hello world'


37

เพียงเพื่อขยายเล็กน้อย ... คุณสามารถรันโค้ดโดยตรงในการsetTimeoutโทร แต่เป็น@patrickพูดว่าปกติคุณจะกำหนดฟังก์ชั่นการโทรกลับเช่นนี้ เวลาเป็นมิลลิวินาที

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

27

หากคุณต้องการให้มีdelayฟังก์ชั่นการปิดกั้น (ซิงโครนัส) (สำหรับทุกสิ่ง) ทำไมคุณไม่ทำสิ่งนี้:

<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>

2
ความยากในการแก้ปัญหานี้คือมันใช้โปรเซสเซอร์ซึ่งนำไปสู่การใช้พลังงานที่เพิ่มขึ้นและการลดลงของทรัพยากรที่มีอยู่สำหรับเธรด / กระบวนการอื่น ๆ (เช่นแท็บอื่น ๆ โปรแกรมอื่น ๆ ) ในทางตรงกันข้ามสลีปจะระงับการใช้ทรัพยากรระบบของเธรดชั่วคราว
ramcdougal

1
ดีกว่าที่จะใช้ Date.now () แทน Date ใหม่ () และอย่าคิดถึงการรั่วไหลของหน่วยความจำ
WayFarer

1
แน่นอนว่ามันเป็น CPU ที่เข้มข้น แต่สำหรับการทดสอบที่รวดเร็วและสกปรกมันทำงานได้ดี
Maris B.

ฉันต้องการเวอร์ชันที่ไม่ล็อคเธรดดังนั้นฉันสามารถรีเฟรช DOM ก่อนที่จะส่งdelay(เพื่อตอบคำถามนี้ ) มีวิธีการทำเช่นนั้น?
Gui Imamura

3
รูทีนกระชับยิ่งขึ้น: function delay (ms) {var start_time = Date.now (); ในขณะที่ (Date.now () - start_time <ms); }
Duke

15

คุณต้องใช้setTimeoutและส่งผ่านฟังก์ชันการโทรกลับ เหตุผลที่คุณไม่สามารถใช้ sleep ใน javascript ได้ก็เพราะคุณปิดกั้นหน้าเว็บทั้งหมดไม่ให้ทำอะไรเลยในระหว่างนี้ ไม่ใช่แผนการที่ดี ใช้รูปแบบกิจกรรมของ Javascript และมีความสุข อย่าสู้กับมัน!


2
แต่ถึงกระนั้นมันก็จะมีประโยชน์สำหรับการทดสอบ เช่นเดียวกับการล่าช้าการส่งแบบฟอร์มสักครู่เพื่อประเมินการเปลี่ยนแปลงหน้าก่อนที่จะมีการร้องขอ HTTP ใหม่
Rushinge

1
@rushinge แล้วตั้งค่าให้โทรกลับเพื่อส่งแบบฟอร์มและปิดการใช้งานแบบฟอร์มเริ่มต้นส่ง
Populus

1
ความคิดที่ดีที่จะทิ้งลิงค์ไว้เป็นรหัส ... เพราะตอนนี้มันใช้งานไม่ได้
Emmet Arries

1
หรือคุณรู้ว่าฉันสามารถแก้ไขได้
แพทริค

14

นอกจากนี้คุณยังสามารถใช้window.setInterval ()เพื่อเรียกใช้รหัสซ้ำ ๆ ในช่วงเวลาปกติ


2
setInterval () ไม่ควรใช้แทนควรใช้ setTimeout
paul

9
setTimeout()ทำครั้งเดียวsetInterval()ทำซ้ำหลาย ๆ ครั้ง หากคุณต้องการให้รหัสของคุณทำงานทุก ๆ 5 วินาทีsetInterval()จะถูกสร้างขึ้นสำหรับงานนี้
rcoup

11

เพื่อเพิ่มความคิดเห็นก่อนหน้านี้ฉันต้องการจะพูดต่อไปนี้:

setTimeout()ฟังก์ชั่นใน JavaScript ไม่ได้หยุดการทำงานของสคริปต์ต่อ se แต่เพียงบอกคอมไพเลอร์ในการดำเนินการบางครั้งรหัสในอนาคต

ไม่มีฟังก์ชั่นที่สามารถหยุดการประมวลผลที่สร้างไว้ใน JavaScript ได้ อย่างไรก็ตามคุณสามารถเขียนฟังก์ชั่นของคุณเองที่ทำบางสิ่งบางอย่างเช่นการวนซ้ำแบบไม่มีเงื่อนไขจนกว่าจะถึงเวลาโดยใช้Date()ฟังก์ชันและเพิ่มช่วงเวลาที่คุณต้องการ


11

หากคุณต้องการทดสอบความล่าช้าคุณสามารถใช้สิ่งนี้:

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

และถ้าคุณต้องการหน่วงเวลา 2 วินาทีคุณจะทำ:

delay(2000);

อาจไม่ดีที่สุดสำหรับการผลิตแม้ว่า เพิ่มเติมเกี่ยวกับที่อยู่ในความคิดเห็น


@ U2744 SNOWFLAKE คุณลองและแม่นยำกว่านี้ในความคิดเห็นของคุณได้ไหม
Christoffer

1
มันเป็นวงที่ไม่ว่างที่จะระบายแบตเตอรี่ของแล็ปท็อปและอุปกรณ์มือถืออื่น ๆ และอาจป้องกัน UI ไม่ให้ตอบสนอง (หรือแม้แต่แสดง)
Ry-

@ U2744SNOWFLAKE เหมาะสมแล้ว ได้อัปเดตคำตอบสำหรับสิ่งที่ฉันใช้ฟังก์ชั่นนี้เพื่อ :)
Christoffer

2
ทำงานได้ดีพอในการพัฒนาสำหรับโซลูชันที่รวดเร็วและสกปรก (และชั่วคราว)
HumanInDisguise

5

ทำไมคุณไม่สามารถใส่รหัสตามสัญญา? (พิมพ์ที่ด้านบนของหัวของฉัน)

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


5

คำตอบง่ายๆคือ:

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

ฟังก์ชั่นด้านบนรอ 1 วินาที (1,000 ms) จากนั้นตั้งค่า x เป็น 1 เห็นได้ชัดว่านี่เป็นตัวอย่าง; คุณสามารถทำสิ่งที่คุณต้องการในฟังก์ชั่นที่ไม่ระบุชื่อ


4

ผมชอบ Maurius' คำอธิบาย (การตอบสนอง upvoted สูงสุด) setTimeoutมีสามวิธีที่แตกต่างกันสำหรับการโทร

ในรหัสของฉันฉันต้องการอัตโนมัตินำทางไปยังหน้าก่อนหน้าโดยอัตโนมัติเมื่อเสร็จสิ้นการบันทึกเหตุการณ์ AJAX ความสมบูรณ์ของเหตุการณ์บันทึกมีภาพเคลื่อนไหวเล็กน้อยใน CSS ที่ระบุว่าบันทึกสำเร็จ

ในรหัสของฉันฉันพบความแตกต่างระหว่างสองตัวอย่างแรก:

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

อันนี้ไม่รอการหมดเวลา - back () ถูกเรียกเกือบจะทันทีไม่ว่าฉันจะใส่เบอร์ไหนสำหรับความล่าช้า

อย่างไรก็ตามการเปลี่ยนสิ่งนี้เป็น:

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

สิ่งนี้ทำในสิ่งที่ฉันหวังอย่างแน่นอน

นี้ไม่ได้เป็นเฉพาะกับการดำเนินงานกลับ () alert()เดียวกันที่เกิดขึ้นกับ โดยพื้นฐานแล้วจะalert()ใช้ในกรณีแรกเวลาล่าช้าจะถูกละเว้น เมื่อฉันปิดป๊อปอัพภาพเคลื่อนไหวสำหรับ CSS จะดำเนินต่อไป

ดังนั้นฉันขอแนะนำวิธีที่สองหรือสามที่เขาอธิบายแม้ว่าคุณจะใช้ฟังก์ชันที่มีอยู่แล้วและไม่ใช้อาร์กิวเมนต์


1

ฉันมีคำสั่ง ajax ที่ฉันต้องการเรียกใช้โดยมีความล่าช้าในระหว่างนั้น นี่คือตัวอย่างง่ายๆของวิธีหนึ่งในการทำเช่นนั้น ฉันพร้อมที่จะถูกฉีกเป็นชิ้นเล็กชิ้นน้อย แต่สำหรับวิธีการที่แปลกใหม่ของฉัน :)

//  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());

คุณสามารถคัดลอกบล็อครหัสและวางลงในหน้าต่างคอนโซลและดูดังนี้:

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

1

ทางออกที่ง่ายที่สุดในการเรียกใช้ฟังก์ชันของคุณด้วยความล่าช้าคือ:

function executeWithDelay(anotherFunction) {
    setTimeout(anotherFunction, delayInMilliseconds);
}

0

ฟังก์ชั่นล่าช้า:

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

การใช้งานภายในasyncฟังก์ชั่น:

await delay(1000);

-1

อย่างที่คนอื่นพูดว่า setTimeout เป็นเดิมพันที่ปลอดภัยที่สุดของคุณ
แต่บางครั้งคุณไม่สามารถแยกลอจิกกับฟังก์ชั่นใหม่จากนั้นคุณสามารถใช้ Date.now () เพื่อรับมิลลิวินาทีและทำการหน่วงเวลาด้วยตัวคุณเอง ....

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());

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.