sleep เวอร์ชัน JavaScript คืออะไร?


2335

มีวิธีที่ดีกว่าในการสร้าง a sleepJavaScript ในpausecompฟังก์ชั่นต่อไปนี้( จากที่นี่ )?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

นี้ไม่ได้เป็นซ้ำของการนอนใน JavaScript - ความล่าช้าระหว่างการกระทำ ; ฉันต้องการให้สลีปจริงในระหว่างฟังก์ชั่นและไม่ใช่ความล่าช้าก่อนที่โค้ดจะประมวลผล


4
มันเป็นชุดในช่วงกลางของในขณะที่ถ้าใช้ i setTimeout ในขณะที่จะยังคงที่จะดำเนินการและคิว setTimeouts มากขึ้นซึ่งจะได้รับการทำงานในเวลาเดียวกันและทำให้บิตของการทำงานพร้อมกันระหว่างตัวเอง
FMSF

159
นี่คือวิธีการแก้ปัญหาที่น่ากลัว - คุณกำลังจะได้รับการเคี้ยวการประมวลผลรอบในขณะที่ทำอะไร
17 ของ 26

12
วัตถุประสงค์เดียวของการนอนหลับคือการสำรวจหรือรอการติดต่อกลับ - setInterval และ setTimeout ทำได้ดีกว่านี้
annakata

1
น่าจะเป็นที่คุณสามารถทำสิ่งที่คุณต้องการกับรูปแบบการส่งผ่านความต่อเนื่องใน JavaScript ลองดูที่บทความนี้
Ognyan Dimitrov

คำตอบ:


2560

อัพเดต 2017 - 2019

นับตั้งแต่ปี 2009 เมื่อคำถามนี้ถูกถาม, JavaScript มีการพัฒนาอย่างมีนัยสำคัญ คำตอบอื่น ๆ ตอนนี้ล้าสมัยหรือซับซ้อนเกินไป นี่คือแนวปฏิบัติที่ดีที่สุดในปัจจุบัน:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

นี่ไง. await sleep(<duration>).

หรือเป็นหนึ่งซับ:

await new Promise(r => setTimeout(r, 2000));

ทราบว่า

  1. awaitสามารถเรียกใช้งานในฟังก์ชั่นนำหน้าด้วยasyncคำหลักหรือที่ระดับสูงสุดของสคริปต์ของคุณในบางสภาพแวดล้อม (เช่นคอนโซล Chrome DevTools หรือ Runkit)
  2. awaitหยุดasyncฟังก์ชั่นปัจจุบันเท่านั้น

คุณสมบัติ JavaScript ใหม่สองรายการช่วยให้เขียนฟังก์ชัน "sleep" นี้:

ความเข้ากันได้

หากมีเหตุผลแปลก ๆ ที่คุณใช้โหนดที่เก่ากว่า 7 (ซึ่งสิ้นสุดอายุการใช้งาน ) หรือกำหนดเป้าหมายเป็นเบราว์เซอร์เก่าasync/ awaitสามารถใช้ผ่านBabel ได้ (เครื่องมือที่จะtranspile JavaScript + คุณสมบัติใหม่เป็น JavaScript เก่าแบบธรรมดา) กับtransform-async-to-generatorปลั๊กอิน


5
สิ่งที่ดีที่นี่ ฉันสงสัยว่าสิ่งนี้มีผลกระทบหรือเกี่ยวข้องกับเบราว์เซอร์ที่ทันสมัย ​​"ใช้งาน" / "ไม่ได้ใช้งาน" รัฐหลังจาก JS เรียกโหมด "นอน" เบราว์เซอร์สามารถปิดกั้นการสลีปตามที่คาดไว้สำหรับ JS ทั่วไปเพื่อเรียกคืนในภายหลังเมื่อกลายเป็น "แอ็คทีฟ" หรือมีพฤติกรรมที่แตกต่างออกไปหรือไม่?
Andre Canilho

18
เบราว์เซอร์ปัจจุบันรองรับอะไรบ้าง ฉันจะไม่พิจารณาวิธีแก้ไขปัญหาก่อนหน้านี้ว่า "ล้าสมัย" จนกว่าโซลูชันนี้จะได้รับการสนับสนุนโดยเบราว์เซอร์ส่วนใหญ่หรืออย่างน้อยก็เป็นโซลูชันทั่วไป ในทางตรงกันข้ามฉันจะพิจารณาวิธีนี้น่าสนใจ แต่ใช้ไม่ได้ / ใช้ไม่ได้จนกว่าจะได้รับการสนับสนุนอย่างกว้างขวาง
อัลวิน ธ อมป์สัน

74
นี่ไม่ใช่ "การนอนหลับจริง" และไม่ตอบคำถาม คนที่ถามชัดเจนชัดเจนระหว่างstackoverflow.com/questions/758688/sleep-in-javascriptกับคำถามของเขา ในโหมดสลีปจริงจะไม่สามารถเรียกใช้รหัสอื่น (ยกเว้นในเธรดอื่น) คำตอบนี้ดีสำหรับคำถามอื่น
niry

4
@jacroe - จับ transpiler ลูกศรฟังก์ชั่นเช่นเดียวกับ async / รอคอย (ซึ่งจะทำให้ IE เพื่อเลือดอาเจียนอยู่แล้ว)
Jaromanda X

11
@niry JavaScript ซึ่งเป็นภาษาแบบเธรดเดียวไม่เหมาะสำหรับการนอน "จริง" เนื่องจากมันทำงานบนเธรดเดียวกับ UI และอาจทำให้หน้าเว็บไม่ตอบสนอง
Patrick Roberts

849

(ดูคำตอบล่าสุดสำหรับปี 2559 )

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

ปัญหาที่นี่คือ JavaScript เป็นรูปแบบเหตุการณ์แบบเธรดเดียว ในบางกรณีมันอาจจะดีถ้าให้ทั้งเครื่องยนต์รอสักครู่โดยทั่วไปมันเป็นการฝึกฝนที่แย่ สมมติว่าฉันต้องการใช้ฟังก์ชั่นของคุณในขณะที่เขียนด้วยตัวเอง? เมื่อฉันเรียกวิธีการของคุณวิธีการของฉันทั้งหมดจะหยุด หาก JavaScript สามารถรักษาบริบทการทำงานของฟังก์ชันของคุณให้เก็บไว้ที่ใดที่หนึ่งจากนั้นนำกลับมาและดำเนินการต่อในภายหลังจากนั้นสลีปอาจเกิดขึ้นได้

ดังนั้นคุณค่อนข้างติดอยู่กับสิ่งที่คนอื่นแนะนำ - คุณจะต้องแยกรหัสของคุณออกเป็นหลายฟังก์ชั่น

คำถามของคุณเป็นตัวเลือกที่ผิดเล็กน้อย ไม่มีทางที่จะนอนในแบบที่คุณต้องการและคุณไม่ควรทำตามวิธีที่คุณแนะนำ


45
นี่ไม่ใช่คำตอบที่ถูกต้องเลย หาก Javascript ไม่มีฟังก์ชั่น sleep นั่นก็เป็นเพราะ ECMAScript ไม่ต้องการมัน เป็นตัวเลือกการออกแบบโดยหน่วยงานที่รับผิดชอบการออกแบบ Javascript อาจเป็นไปได้ว่าเวลาเรียกใช้ Javascript รอเวลาตามจำนวนที่กำหนดก่อนที่จะรันโค้ดบรรทัดถัดไป แต่ไม่ได้เลือก
Didier A.

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

ลองสะกดจิตซึ่งตามแนวคิดนี้: coolwanglu.github.io/hypnotic/web/demo.html
Tezcat

4
การเรียกใช้จาวาสคริปต์แบบเธรดเดียวเป็นเพียงตำนาน ในขณะที่มันอาจถูกต้องทางเทคนิคมันทำหน้าที่เหมือนเป็นหลายเธรด การจำลอง fork () นั้นง่ายนิดเดียวและถึงแม้ว่า yield () จะไม่สามารถนำไปใช้ได้จริง ๆ คุณสามารถเข้าใกล้ได้โดยใช้หน่วยความจำที่แชร์เพื่อล็อค / เซมาฟอร์ สำหรับโปรแกรมเมอร์โดยเฉลี่ยมันสมเหตุสมผลที่จะถือว่ามันเป็นแบบมัลติเธรด ชื่อทางเทคนิคมีความสำคัญต่อผู้พัฒนาภาษาเท่านั้น
Benubird

8
ฉันยอมรับว่าทำไมsleep()เป็นไปไม่ได้ใน JS และส่วนใหญ่มีวิธีที่ดีกว่าในการทำสิ่งต่าง ๆ แต่ฉันยังคงพิจารณาถึงวิธีที่เครื่องยนต์เชื่อมโยงทุกสิ่งเข้าด้วยกันเพื่อให้เป็นข้อบกพร่องในการออกแบบ ไม่มีเหตุผลที่ภาษาไม่สามารถมีsleep()ฟังก์ชั่นที่ จำกัด เฉพาะสคริปต์หน้าหรือฟังก์ชั่นโดยไม่ต้องใช้เอ็นจิ้นอุดตันซีพียูและแช่แข็งแอพอย่างบ้าคลั่ง มันเป็น 2015 while(1)แล้วคุณจะไม่สามารถที่จะผิดพลาดเว็บเบราว์เซอร์ทั้งหมดที่มี เรามี Flash สำหรับสิ่งต่าง ๆ เช่นนั้น
Beejor

660

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

เวลาที่ฉันอยากนอนในช่วงกลางของฟังก์ชั่นของฉันทุกฉัน refactored setTimeout()ใช้

แก้ไข

นอนหลับน่าอับอายหรือความล่าช้า, ฟังก์ชั่นภายในภาษาใด ๆ ที่เป็นที่ถกเถียงกันมาก บางคนจะบอกว่าควรมีสัญญาณหรือโทรกลับเพื่อให้เกิดการทำงานที่กำหนดไว้เสมอคนอื่นจะยืนยันว่าบางครั้งช่วงเวลาล่าช้าโดยพลการนั้นมีประโยชน์ ฉันบอกว่าแต่ละกฎของพวกเขาและกฎเดียวไม่สามารถบงการอะไรในอุตสาหกรรมนี้

การเขียนฟังก์ชั่นการนอนหลับนั้นง่ายและทำให้สามารถใช้งานได้ดียิ่งขึ้นด้วยสัญญา JavaScript:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

190
โดยวิธีการปิด function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
ความวุ่นวาย

68
ตกลงและถ้ารหัสไม่ได้มีวัตถุประสงค์เพื่อใช้ในหน้าเว็บ?
Eugenio Miró

10
@ EugenioMiróถ้ารหัสไม่ได้มีวัตถุประสงค์เพื่อใช้ในเว็บเพจให้โมเดลวัตถุของโฮสต์ใช้เมธอด sleep - ฉันคิดว่าคำถามนั้นมุ่งไปที่ DOM ซึ่งมีการเปิดใช้จาวาสคริปต์ในหน้าเว็บ
BrainSlugs83

31
@Nosredna ใช่เราเข้าใจวิธีการโทรแบบ async นี่ไม่ได้ช่วยให้เรานอนหลับ () ฉันต้องการให้การโทรของฉันเป็นไปตามลำดับและมีข้อมูลกลับมาในลำดับที่แน่นอน ฉันอยู่ลึกลงไปอีก 5 ระดับ ฉันต้องการประหาร BLOCK วิธีการนอนหลับที่แท้จริงจะไม่ "ชะลอเบราว์เซอร์" มือสลีปควบคุมกลับไปที่เบราว์เซอร์และเธรดอื่น ๆ ที่ต้องการเวลา CPU ในขณะที่ยังคงบล็อกอยู่
BrainSlugs83

382
นี่ไม่ใช่คำตอบสำหรับคำถาม
TMS

303

เฉพาะการดีบัก / devฉันโพสต์สิ่งนี้หากเป็นประโยชน์กับใครบางคน

สิ่งที่น่าสนใจใน Firebug (และอาจเป็นคอนโซล js อื่น ๆ ) ไม่มีอะไรเกิดขึ้นหลังจากกดปุ่ม Enter หลังจากระยะเวลาการนอนหลับที่ระบุเท่านั้น (... )

function sleepFor( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
}

ตัวอย่างการใช้งาน:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }

36
นี่ไม่ใช่คำตอบ มันเหมือนกับรหัสในคำถามยกเว้นสั้นกว่าเล็กน้อย
jab

16
ไม่ว่างรอจริงเหรอ? ใน JS? สำหรับวินาที? ถ้าฉันจับเว็บไซต์ที่ทำสิ่งนี้มันจะถูกปิดกั้น
mafu

34
@mafu นั่นเป็นเหตุผลที่มันบอกว่าonly for debug/dev... rolleyes
xDaizu

11
ไม่เคยทำเช่นนี้ สิ่งนี้จะทำให้ซีพียูชน 100% บนแกนประมวลผลและจะบล็อค
noego

3
สิ่งนี้มีประโยชน์และอาจเป็นวิธีเดียวเท่านั้นที่จะหลับภายในแอปพลิเคชันจาวาสคริปต์บรรทัดคำสั่งเนื่องจาก async / await ไม่เป็นประโยชน์
Wheezil

177

ฉันเห็นด้วยกับโปสเตอร์อื่น ๆ การนอนไม่ว่างเป็นเพียงความคิดที่ไม่ดี

อย่างไรก็ตาม setTimeout ไม่หยุดการทำงานมันจะประมวลผลบรรทัดถัดไปของฟังก์ชั่นทันทีหลังจากหมดเวลาใช้งานคือ SET ไม่ใช่หลังจากหมดเวลาหมดอายุดังนั้นจึงไม่สามารถทำภารกิจเดียวกับที่สลีปสำเร็จ

วิธีที่จะทำคือการแบ่งการทำงานของคุณในการก่อนและหลังส่วน

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

ตรวจสอบให้แน่ใจว่าชื่อฟังก์ชั่นของคุณยังคงอธิบายสิ่งที่แต่ละชิ้นกำลังทำอยู่อย่างถูกต้อง (IE GatherInputThenWait และ CheckInput มากกว่า funcPart1 และ funcPart2)

แก้ไข

วิธีนี้บรรลุวัตถุประสงค์ในการไม่รันบรรทัดของโค้ดที่คุณตัดสินใจจนกระทั่งหลังจากหมดเวลาใช้งานในขณะที่ยังคงกลับการควบคุมกลับไปที่พีซีไคลเอ็นต์เพื่อดำเนินการสิ่งอื่น ๆ ที่อยู่ในคิว

แก้ไขเพิ่มเติม

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


12
ใช่. เมื่อคุณมีลูปหรือลูปซ้อนกัน คุณต้องละทิ้งลูปและมีเคาน์เตอร์แทน
Nosredna

Touch? ฉันหมายความว่ามันจะยังคงเป็นไปได้ แต่น่าเกลียดและแฮ็คในกรณีนั้น คุณสามารถใช้ตัวแปรสถานะบูลีนแบบสแตติกได้ แต่นั่นก็ค่อนข้างแฮ็คเช่นกัน
DevinB

2
-1 สำหรับสิ่งนี้ อีกครั้งนี้ไม่ตอบคำถาม นี่เป็นคำตอบเพิ่มเติมสำหรับคำถามเช่น "วิธีการใช้งานฟังก์ชั่นแบบอะซิงโครนัส" ซึ่งแตกต่างจาก "วิธีบล็อกการเรียกใช้โค้ด" อย่างมาก
Deepak GM

6
@Nosredna ไม่คุณต้องปิดตัวเอง ตัวอย่างเช่น: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); }และfor(var X = 0; X < 3;X++) { foo(X); }- ค่าของ X จะถูกส่งเข้าไปfooซึ่งจะถูกนำกลับมาใช้ใหม่ภายใต้ชื่อindexเมื่อfoo_continueในที่สุดเรียกว่า
Izkata

2
@Alexander แน่นอนมันทำเพราะจุดของ setTimeout () คือการป้องกันเบราว์เซอร์จากการล็อคโดยใช้รหัส asychronously ใส่console.log()ข้างfoo_continue()ในในเวอร์ชัน setTimeout และคุณจะได้ผลลัพธ์เดียวกัน
Izkata

132

สำหรับความรักของ $ DEITY โปรดอย่าสร้างฟังก์ชั่นการนอนหลับรอคอย setTimeoutและsetIntervalทำทุกสิ่งที่คุณต้องการ

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
    ;
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

ทุกช่วงเวลาสองวินาทีซ่อนข้อความเป็นเวลาหนึ่งวินาที สิ่งนี้แสดงวิธีการใช้ setInterval และ setTimeout เพื่อแสดงและซ่อนข้อความในแต่ละวินาที


3
ไม่ใช่ทุกอย่างเลย: setInterval จะสร้างความประทับใจในการลงคะแนนเลือกตั้งได้ดีกว่ามาก
annakata

3
ส่วนใดของรหัสที่จะไม่ถือกลับในเครื่องมือ JavaScript?
Deniz Dogan

10
ถ้าคุณไม่ต้องการให้โหมดสลีปซิงโครนัสซึ่งในกรณีนี้เป็นคำถามที่ถูกต้องสมบูรณ์
Aaron Dufour

36
ฉันคิดว่าพวกเราหลายคนอาจลืมว่า JavaScript ไม่ใช่ภาษาเดียวของเบราว์เซอร์ เพื่อนคนนี้อาจกำลังสร้างยูทิลิตีบรรทัดคำสั่ง Node ที่ต้องการหยุดสั้น ๆ โดยไม่จำเป็นต้องจัดการกับปัญหาการกำหนดขอบเขตตัวแปรทั้งหมดที่มาพร้อมกับ setTimeout
Phil LaNasa

3
@PhilLaNasa: หากการปิดประโยคยังคงทำให้ตกใจใครจะต้องจริงจังและทำงานผ่าน Node 101
chaos

113

ฉันรู้ว่านี่เป็นคำถามเก่า ๆ แต่ถ้า (เช่นฉัน) คุณกำลังใช้ Javascript กับ Rhino คุณสามารถใช้ ...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}

4
นี่เป็นการโทรไปยัง Java หรือไม่
Ken Sharp

14
นี่คือJavaไม่ใช่Javascript
RousseauAlexandre

18
@RousseauAlexandre ไม่ถูกต้อง มันเป็นจาวาสคริปต์ที่ใช้แรด (ในเวลานั้นมันก็อาจจะเท่ากันแนชวันนี้)
mjaggard

71

หากคุณกำลังใช้ jQuery มีคนสร้างปลั๊กอิน "ล่าช้า" ซึ่งไม่มีอะไรมากไปกว่าเสื้อคลุมสำหรับ setTimeout

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

จากนั้นคุณสามารถใช้ฟังก์ชันนี้ในการเรียกใช้ฟังก์ชันตามที่คาดไว้:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

4
นั่นไม่ใช่ทางออกที่ไม่ดี รักษาบริบทและความสามารถในการเชื่อมโยง
Nosredna

39
ในฐานะของ jQuery 1.4 .delay()เป็นส่วนหนึ่งของ jQuery (แม้ว่าจะมีความหมายแตกต่างจากการใช้งานด้านบน) api.jquery.com/delay
แมตต์บอล

7
อะไรคำถามนี้ถูกแน่นอนขาดเป็นคำตอบ jQuery ดีใจที่เราได้รับมัน!
xDaizu

1
หากคุณต้องการความล่าช้าระหว่างการโทรอิสระสองสายใช่ หากคุณต้องการความล่าช้าในการชะลอการวนซ้ำ
WGroleau

46

ฉันได้ค้นหาวิธีแก้ปัญหาการนอนหลับด้วย (ไม่ใช่สำหรับรหัสการผลิตเฉพาะสำหรับการทดสอบ dev / การทดสอบ) และพบบทความนี้:

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

... และนี่คือลิงค์อื่นที่มีโซลูชันฝั่งไคลเอ็นต์: http://www.devcheater.com/

นอกจากนี้เมื่อคุณโทรalert()รหัสของคุณจะถูกหยุดชั่วคราวในขณะที่การแจ้งเตือนแสดงขึ้น - ต้องหาวิธีที่จะไม่แสดงการแจ้งเตือน แต่ได้รับผลกระทบเดียวกัน :)


35
ฉันเห็นด้วยผู้คนจำนวนมากกำลังพูดว่า "ไม่อย่าทำอย่างนี้ในรหัสการผลิต!" ใช่อืมฉันไม่ต้องการ ฉันต้องการที่จะทำมันในรหัสทดสอบทิ้งและดังนั้นฉันไม่ต้องการใช้เวลามากในการทำทางออกที่สวยงาม
user435779

31

นี่เป็นวิธีง่ายๆในการใช้ XMLHttpRequest แบบซิงโครนัส:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

เนื้อหาของ sleep.php:

<?php sleep($_GET['n']);

ตอนนี้เรียกว่าด้วย: sleep (5);


5
@ lukad ใช้setTimeout()ถ้าใช้งานได้ แต่ถ้าทำเช่นนั้นหมายถึงการแก้ไขการเรียกกลับ 1000 บรรทัดซึ่งอาจเริ่มดูไม่เป็นเรื่องตลก
pguardiario

11
วิธีการที่ไม่ซ้ำกัน แต่น่าเสียดายที่ไม่ใช่ async XMLHttpRequests จะเลิกใช้แล้วและจะถูกลบออกในอนาคต ซึ่งเป็นเรื่องตลกเพราะความจริงนั้นคือสิ่งที่นำฉันไปสู่คำถามนี้ในตอนแรก
Beejor

นี่เป็นความคิดที่ดีทีเดียวสำหรับ IMO แม้ว่าฉันไม่คิดว่า API การนอนหลับ (URL คำขอ) ควรเป็นสาธารณะเนื่องจากสามารถถูกละเมิดได้
Vahid Amiri

@Beejor คิดอยู่เสมอเกี่ยวกับอนาคตหมายถึงการใช้ชีวิตบนความไร้อนาคต :-)
user1742529

ดี แต่คุณรู้หรือไม่ว่าบางครั้งอินเทอร์เน็ตช้าหรือเวลา ping ของเว็บไซต์สูงกว่าสคริปต์การนอนหลับนานกว่าเวลาโต้แย้ง เช่นถ้าคุณใช้sleep(300)และเว็บไซต์ใช้เวลา 150 มิลลิวินาทีในการตอบสนองมากกว่าโค้ดจาวาสคริปต์จะเข้าสู่โหมดสลีปเป็นเวลา 450 มิลลิวินาที และหากการเชื่อมต่ออินเทอร์เน็ตขาดหายไปโดยเบราว์เซอร์จะทำงานได้เพียง 0ms ดังนั้นจึงไม่ใช่ทางออกที่ดีกว่า
H Chauhan

30

ไปเลย ตามที่รหัสบอกไว้อย่าเป็น dev ที่ไม่ดีและใช้สิ่งนี้บนเว็บไซต์ มันเป็นฟังก์ชั่นการพัฒนายูทิลิตี้

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}

17
นั่นเป็นสิ่งเดียวกับที่ OP มี
Andrew Barber เมื่อ

5
เพื่อให้แม่นยำยิ่งขึ้นมันเป็นสิ่งที่ OP ขอให้เป็นทางเลือก
WGroleau

การแก้ปัญหาไม่ดี แต่ในบางสถานที่async/awaitมันไม่ตอบสนองอย่างน่าเสียดายและเราต้องใช้มันอย่างชัดเจน
Nabi KAZ

21

ฉันชอบความเรียบง่าย:

function sleep(seconds){
    var waitUntil = new Date().getTime() + seconds*1000;
    while(new Date().getTime() < waitUntil) true;
}

แล้ว:

sleep(2); // Sleeps for 2 seconds

ฉันใช้มันตลอดเวลาเพื่อสร้างเวลาโหลดปลอมในขณะที่สร้างสคริปต์ใน P5js


3
ฉันเห็นว่านี่เป็นคำถามหลักที่ได้รับการปรับให้เหมาะสมที่สุด: มันไม่ได้ทำการคำนวณทางคณิตศาสตร์ใด ๆ ภายในลูป แต่เป็นการเปรียบเทียบธรรมดา มันอ่านยากนิดหน่อย
hegez

4
ไม่เคยทำเช่นนั้น คุณตรวจสอบการใช้งาน CPU ในขณะที่ฟังก์ชั่นนี้ใช้งานได้หรือไม่? ควรใกล้เคียง 100% ถ้าคุณให้เวลากับมันมากพอ
noego

2
@ hegez: เนื่องจากการวนซ้ำจะทำงานเป็นเวลานาฬิกาแขวนคงที่ไม่ว่าจะเป็นอะไรก็ตามดูเหมือนว่าการปรับแต่งการวนรอบให้เหมาะสมนั้นอยู่ด้านข้างจุด
ShadowRanger

@ ไม่เหมือนกันเหรอ? ฉันเพิ่งทดสอบใน Node 10 ฉันไม่มีการเปลี่ยนแปลงการใช้งาน CPU เลย
melMass

@melMass ฟังก์ชั่นนี้จะบล็อกเธรดโหนดเป็นเวลา n วินาทีโดยทำให้ CPU ไม่ว่าง 100% "การแก้ไขปัญหา" นี้เป็นแนวคิดที่ไม่ดีอย่างยิ่งสำหรับทั้งสองเหตุผล (การบล็อก + ตัวทำลาย CPU) กำลังรอ HAS เป็นการไม่บล็อกดังนั้นแบบอะซิงโครนัส
Jeremy Thille

20

ครั้งแรก:

กำหนดฟังก์ชั่นที่คุณต้องการใช้งานดังนี้:

function alertWorld(){
  alert("Hello World");
}

จากนั้นกำหนดเวลาดำเนินการด้วยเมธอด setTimeout:

setTimeout(alertWorld,1000)

สังเกตสองสิ่ง

  • อาร์กิวเมนต์ที่สองคือเวลาเป็น miliseconds
  • เป็นอาร์กิวเมนต์แรกคุณต้องผ่านเพียงชื่อ (การอ้างอิง) ของฟังก์ชันโดยไม่มีวงเล็บ

19

  await new Promise(resolve => setTimeout(resolve, 2000));

ตรวจสอบให้แน่ใจว่าฟังก์ชันการโทรของคุณเป็นแบบซิงค์

ตรวจสอบและทำงานได้ดี


1
ในที่สุด คำตอบเดียวเท่านั้น
Jeremy Thille

18

ทางออกที่ดีกว่าในการทำให้สิ่งต่าง ๆ ดูเหมือนว่าสิ่งที่คนส่วนใหญ่ต้องการคือการใช้ฟังก์ชั่นนิรนาม:

alert('start');
var a = 'foo';
//lots of code
setTimeout(function(){  //Beginning of code that should run AFTER the timeout
    alert(a);
    //lots more code
},5000);  // put the timeout here

นี่อาจเป็นสิ่งที่ใกล้เคียงที่สุดที่คุณจะไปถึงสิ่งที่ทำในสิ่งที่คุณต้องการ

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


นี่คืออันที่ทำงานกับฉันบนเบราว์เซอร์เดสก์ท็อปและโทรศัพท์มือถือรุ่นเก่า คนอื่นที่ฉันพยายามไม่ทำงานทั้งหมด
Mike

10

สำหรับเบราว์เซอร์ฉันยอมรับว่า setTimeout และ setInterval เป็นวิธีที่จะไป

แต่สำหรับรหัสฝั่งเซิร์ฟเวอร์มันอาจต้องใช้ฟังก์ชั่นการปิดกั้น (ตัวอย่างเช่นเพื่อให้คุณสามารถมีการประสานด้ายได้อย่างมีประสิทธิภาพ)

หากคุณใช้ node.js และ meteor คุณอาจพบข้อ จำกัด ในการใช้ setTimeout ในไฟเบอร์ นี่คือรหัสสำหรับฝั่งเซิร์ฟเวอร์

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

ดู: https://github.com/laverdet/node-fibers#sleep


Server may require a blocking function... ฉันไม่เห็นว่าการบล็อกเธรดเพียงอย่างเดียวของโหนดและทำให้เซิร์ฟเวอร์ทั้งหมดของคุณไม่ตอบสนองเป็นเวลาหลายวินาทีเป็นความคิดที่ดี แต่ไม่ว่าอะไรก็ตาม
Jeremy Thille

10

ฉันจะสรุป setTimeOut ในสัญญาเพื่อความสอดคล้องของรหัสกับงานอะซิงโครนัสอื่น ๆ : การสาธิตในซอ

function sleep(ms)
{
    return(new Promise(function(resolve, reject) {        
        setTimeout(function() { resolve(); }, ms);        
    }));    
}

ใช้แบบนั้น:

sleep(2000).then(function() { 
   // Do something
});

มันง่ายต่อการจดจำไวยากรณ์ถ้าคุณเคยใช้ Promises


4
ทำไมจึงดีกว่าแค่ใช้ setTimeout (function () {/ * ทำบางสิ่ง * /}, 2000);
JSideris

10

2019 อัปเดตโดยใช้Atomics.wait

ควรทำงานในโหนด 9.3 หรือสูงกว่า

ฉันต้องการตัวจับเวลาที่แม่นยำใน Node.js และใช้งานได้ดีสำหรับสิ่งนั้น อย่างไรก็ตามดูเหมือนว่ามีการสนับสนุนที่ จำกัด อย่างมากในเบราว์เซอร์

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

วิ่งสองสามวินาทีมาตรฐานการจับเวลา

ด้วย setTimeout ฉันได้รับข้อผิดพลาดสูงถึง 7000 microseconds (7Ms)

ด้วย Atomics ข้อผิดพลาดของฉันดูเหมือนจะต่ำกว่า 600 microseconds (0.6ms)

2020 Update: โดยสรุป

function sleep(millis){ // need help of a server-side page
  let netMillis=Math.max(millis-5,0); //assuming 5ms overhead
  let xhr=new XMLHttpRequest();
  xhr.open('GET','/sleep.jsp?millis='+netMillis+'&rand='+Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}
function sleepAsync(millis){ // use only in async function
  let netMillis=Math.max(millis-1,0); // assuming 1ms overhead
  return new Promise((resolve)=>{
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}
async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}
function sleepSyncTest(){ 
  let source=`${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src='data:text/javascript,'+encodeURIComponent(source);
  console.log(src);
  var worker=new Worker(src);
}

ซึ่งหน้าฝั่งเซิร์ฟเวอร์เช่นsleep.jspดูเหมือนว่า

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>

ในความคิดของฉันดีกว่าโซลูชันที่ยอมรับซึ่งไม่สามารถนำมาใช้เป็นฟังก์ชั่นที่เรียบง่ายโดยไม่ต้อง async / รอในการโทร
GroovyDotCom

ใช่ตราบใดที่คุณทราบว่านี่คือการปิดกั้นและมักจะไม่เป็นสิ่งที่ดี
Kapytanhook

ค่อนข้างเท่ห์ แต่ความจริงที่ว่านี่รองรับเฉพาะChrome และ Firefox เท่านั้นจึงไม่สามารถใช้งานได้บนเว็บ (พ.ย. 2019)
JGreatorex

9

คำตอบส่วนใหญ่ที่นี่มีการเข้าใจผิดหรืออย่างน้อยล้าสมัย ไม่มีเหตุผลจาวาสคริปต์ที่จะต้องมีเธรดเดียวและแน่นอนมันไม่ได้เป็น ทุกวันนี้เบราว์เซอร์หลักสนับสนุนผู้ใช้งานก่อนหน้านี้คือกรณีรันไทม์จาวาสคริปต์อื่น ๆ เช่น Rhino และ Node.js รองรับมัลติเธรด

'Javascript เป็นเธรดเดียว' ไม่ใช่คำตอบที่ถูกต้อง ตัวอย่างเช่นการเรียกใช้ฟังก์ชั่นสลีปภายในผู้ปฏิบัติงานจะไม่บล็อกรหัสใด ๆ ที่ทำงานในเธรด ui

ใน runtimes ที่ใหม่กว่าที่สนับสนุนเครื่องกำเนิดและผลผลิตหนึ่งสามารถนำฟังก์ชันที่คล้ายกันไปยังฟังก์ชัน sleep ในสภาพแวดล้อมเธรดเดียว:

// This is based on the latest ES6 drafts.
// js 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// run code you want to sleep here (ommit star if using js 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // to sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // ommit .value if using js 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// initialize generator and get first sleep for recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// initialize recursive resume function
resume(firstSleep, generator);

การเลียนแบบการนอนหลับนี้แตกต่างจากฟังก์ชั่นการนอนหลับที่แท้จริงเนื่องจากไม่ได้ปิดกั้นเธรด มันเป็นเพียงแค่ฟังก์ชั่น setTimeout ปัจจุบันของ javascript ประเภทการใช้งานนี้ได้รับการใช้งานในTask.jsและควรใช้งานได้แล้ววันนี้ใน Firefox


คนงานไม่ได้ดำเนินการใน IE อย่างน้อยจนถึงเวอร์ชัน 10 ซึ่งปัจจุบันแสดงถึงผู้ใช้จำนวนมาก
Beejor

จริงและถึงแม้จะไม่สามารถนำไปsleepใช้งานได้หลายคน หากใช้ฟังก์ชั่นเครื่องกำเนิด Node.js จะถูกนำมาใช้แล้วและสามารถนำมาใช้ตามที่อธิบายไว้ เบราว์เซอร์หลักยังไม่ได้ใช้กำเนิดทั้งหมด ณ วันนี้
Gabriel Ratener

8

ฉันค้นหา / googled หน้าเว็บจำนวนหนึ่งบน javascript sleep / wait ... และไม่มีคำตอบหากคุณต้องการให้จาวาสคริปต์ "RUN, DELAY, RUN" ... สิ่งที่คนส่วนใหญ่ได้รับคือ "RUN, RUN (ไร้ประโยชน์) เนื้อหา), RUN "หรือ" RUN, RUN + ล่าช้า RUN "....

ดังนั้นฉันจึงกินเบอร์เกอร์และคิด ::: นี่เป็นวิธีแก้ปัญหาที่ได้ผล ... แต่คุณต้องสับรหัสที่ใช้ ... ::: ใช่ฉันรู้ว่านี่เป็นเพียงการอ่าน refactoring ที่ง่ายขึ้น .. ยังคง ...

// ......................................... // ตัวอย่างที่ 1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setInterval
var i = 0;

function run() {
    //pieces of codes to run
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next...
}

run();
t=setInterval("run()",1000);

</script>
</body>
</html>

// .................................... // ตัวอย่างที่ 2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function run() {
    //pieces of codes to run, can use switch statement
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(1000);}
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(2000);}
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(3000);}
    if (i==3){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()",dur);} //starts flow control again after dur

run(); //starts
</script>
</body>
</html>

// ................. ตัวอย่างที่ 3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow
</script>
</body>
</html>

// .............. ตัวอย่างที่ 4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); //stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    i++; //current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow control for first time...
</script>
</body>
</html>

5
ตกลงมันใช้ได้กับ setTimeput แต่มันยากที่จะดูว่าเกิดอะไรขึ้น การใช้ setTimeout นั้นง่ายกว่านี้
naugtur

7
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

มันเหมือนกับคำถามจริง จุดไม่มากทำให้เป็นคำตอบที่แท้จริง
EML

2
ไม่ใช่วิธีแก้ปัญหาที่ดี - การใช้สิ่งนี้ใน JavaScriptExecutor ของ Selenium แขวนเบราว์เซอร์ Chrome ของฉันประมาณ 50% ของเวลาบน 2104 MacBook Pro
กากกะรุน

7

ทางออกที่สั้นที่สุดโดยไม่ต้องพึ่งพาใด ๆ :

await new Promise(resolve => setTimeout(resolve, 5000));

มันไม่ทำงานใน IE11 เราได้รับข้อผิดพลาดทางไวยากรณ์สำหรับฟังก์ชั่นลูกศร
DDphp

@ การใช้ Java-DKawait new Promise(function(resolve) { setTimeout(resolve, 5000); });
k06a

6

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

ใช้ตัวจับเวลาตามที่ระบุในลิงก์ที่คุณอ้างอิง


6

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


6

ฉันสามารถเข้าใจวัตถุประสงค์ของฟังก์ชั่นสลีปถ้าคุณต้องจัดการกับการทำงานแบบซิงโครนัส ฟังก์ชัน setInterval และ setTimeout จะสร้างเธรดการเรียกใช้งานแบบขนานซึ่งจะส่งกลับลำดับการเรียกใช้กลับไปยังโปรแกรมหลักซึ่งไม่มีประสิทธิภาพหากคุณต้องรอผลลัพธ์ที่กำหนด แน่นอนหนึ่งอาจใช้เหตุการณ์และตัวจัดการ แต่ในบางกรณีไม่ใช่สิ่งที่ตั้งใจ


6

เพิ่มสองบิตของฉัน ฉันต้องการไม่ว่างเพื่อรอการทดสอบ ฉันไม่ต้องการแยกโค้ดเพราะมันจะใช้งานได้เยอะดังนั้นมันง่ายสำหรับฉัน

for (var i=0;i<1000000;i++){                    
     //waiting
  }

ฉันไม่เห็นข้อเสียในการทำเช่นนี้และมันก็หลอกให้ฉัน


นั่นอาจจะถูกรวบรวมออกไป
Viktor Sehr

โปรดอย่าทำอย่างนี้ นี่เป็นการปิดกั้นการโทรเข้าสู่โหมดสลีปซึ่งหมายความว่าจะไม่สามารถเรียกใช้จาวาสคริปต์อื่น ๆ ได้ในขณะที่โค้ดของคุณกำลังใช้งานเธรด JS
Steve Midgley

5
@SteveMidgley "ไม่มีจาวาสคริปต์อื่น ๆ ที่สามารถทำงานได้ในขณะที่โค้ดของคุณกำลังใช้งาน JS thread" ดูเหมือนว่าฉันจะเป็นอย่างที่ OP ต้องการทำ¯_ (ツ) _ / ¯
drigoangelo

1
ฉันเพิ่งทำการทดสอบและดูเหมือนว่าแม้ลูปที่ว่างเปล่าจะบล็อกเบราว์เซอร์และ CPU (ไม่ใช่แค่ JavaScript) และการใช้forลูปจะดำเนินการทันทีเกือบทุกครั้งโดยไม่คำนึงถึงค่าสูงสุดสำหรับiและแม้กระทั่งการวางโค้ดคณิตศาสตร์ที่ซับซ้อนไว้ภายใน ดังนั้นหากคุณรอเพียงไม่กี่มิลลิวินาทีดูเหมือนว่ายังไม่มีทางที่จะนอนหลับได้อย่างงดงามใน JS
Beejor

1 ล้านมีขนาดใหญ่เกินไป สำหรับผม 10k พอ
Vlad

6

มันสามารถทำได้โดยใช้วิธีการนอนหลับของ Java ฉันทดสอบใน FF และ IE แล้วและมันไม่ล็อคคอมพิวเตอร์เคี้ยวทรัพยากรหรือทำให้เซิร์ฟเวอร์ไม่นิยม ดูเหมือนจะเป็นทางออกที่สะอาดสำหรับฉัน

ก่อนอื่นคุณต้องโหลด Java บนหน้าเว็บและทำให้วิธีใช้ได้ เมื่อต้องการทำสิ่งนี้ฉันทำสิ่งนี้:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

จากนั้นสิ่งที่คุณต้องทำเมื่อคุณต้องการหยุดชั่วคราวแบบไม่เจ็บปวดใน JS ของคุณคือ:

java.lang.Thread.sleep(xxx)

โดยที่ xxx คือเวลาเป็นมิลลิวินาที ในกรณีของฉัน (โดยเหตุผล) นี่เป็นส่วนหนึ่งของการปฏิบัติตามคำสั่งซื้อส่วนหลังที่ บริษัท ขนาดเล็กมากและฉันต้องการพิมพ์ใบแจ้งหนี้ที่ต้องโหลดจากเซิร์ฟเวอร์ ฉันทำได้โดยการโหลดใบแจ้งหนี้ (เป็นเว็บเพจ) ลงใน iFrame แล้วพิมพ์ iFrame แน่นอนฉันต้องรอจนกว่าหน้าจะโหลดเต็มก่อนที่จะพิมพ์ดังนั้น JS ต้องหยุดชั่วคราว ฉันทำสิ่งนี้ได้สำเร็จโดยให้หน้าใบแจ้งหนี้ (ใน iFrame) เปลี่ยนเขตข้อมูลฟอร์มที่ซ่อนอยู่ในหน้าหลักด้วยกิจกรรม onLoad และรหัสในหน้าหลักที่จะพิมพ์ใบแจ้งหนี้มีลักษณะเช่นนี้ (ส่วนที่ไม่เกี่ยวข้องตัดเพื่อความชัดเจน):

var isReady = eval('document.batchForm.ready');
isReady.value=0;

frames['rpc_frame'].location.href=url;

while (isReady.value==0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

ดังนั้นผู้ใช้กดปุ่มสคริปต์จะโหลดหน้าใบแจ้งหนี้จากนั้นรอตรวจสอบทุกไตรมาสที่สองเพื่อดูว่าหน้าใบแจ้งหนี้โหลดเสร็จหรือไม่จากนั้นจะปรากฏหน้าจอโต้ตอบการพิมพ์เพื่อให้ผู้ใช้ส่งไปยังเครื่องพิมพ์ QED


12
ดูเหมือนจิตวิญญาณที่น่ากลัวมากเมื่อพิจารณาสิ่งที่ผู้เขียนต้องการจะบรรลุ
xaralis

2
ขึ้นอยู่กับ Java Applets ซึ่งเลิกใช้แล้ว
Vahid Amiri

6

คำตอบจำนวนมากไม่ตอบคำถามโดยตรงและไม่ตอบคำถามนี้ ...

นี่คือสองเซ็นต์ของฉัน (หรือฟังก์ชั่น):

หากคุณต้องการฟังก์ชั่น clunky น้อยกว่าsetTimeoutและsetIntervalคุณสามารถล้อมฟังก์ชันเหล่านั้นไว้ในฟังก์ชั่นที่ย้อนกลับลำดับของอาร์กิวเมนต์และตั้งชื่อที่ดีให้:

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

รุ่น CoffeeScript:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

จากนั้นคุณสามารถใช้ฟังก์ชันเหล่านี้ได้อย่างดีกับฟังก์ชั่นนิรนาม

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

ตอนนี้มันอ่านได้อย่างง่ายดายว่า "หลังจาก N มิลลิวินาที, ... " (หรือ "ทุก ๆ N มิลลิวินาที, ... ")


5

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

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}

5

หากคุณใช้งาน node.js คุณสามารถดูไฟเบอร์ได้ - ส่วนขยาย C ดั้งเดิมไปยังโหนดซึ่งเป็นการจำลองแบบ kinda-multi-threading

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

นี่คือตัวอย่างใหม่จาก readme ของพวกเขาเอง:

// sleep.js

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

- และผลลัพธ์คือ:

$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.