รอ 5 วินาทีก่อนดำเนินการบรรทัดถัดไป


313

ฟังก์ชั่นด้านล่างนี้ไม่ทำงานเหมือนที่ฉันต้องการ การเป็น JS สามเณรฉันไม่สามารถหาสาเหตุได้

ฉันต้องการมันจะรอ 5 วินาทีก่อนที่จะตรวจสอบว่าเป็นnewState-1

ขณะนี้ไม่รอเพียงตรวจสอบทันที

function stateChange(newState) {
  setTimeout('', 5000);

  if(newState == -1) {
    alert('VIDEO HAS STOPPED');
  }
}

คำตอบ:


323

คุณต้องใส่รหัสของคุณในฟังก์ชั่นการโทรกลับที่คุณให้setTimeout:

function stateChange(newState) {
    setTimeout(function () {
        if (newState == -1) {
            alert('VIDEO HAS STOPPED');
        }
    }, 5000);
}

รหัสอื่น ๆ จะดำเนินการทันที


4
ปัญหาหลักคือในบางกรณี (การทดสอบโดยเฉพาะ) นี้ไม่เพียงพอละห้อย ถ้าคุณต้องการนอนหลับเป็นเวลา 500 มิลลิวินาทีก่อนกลับมาจากฟังก์ชั่นเช่นเพื่อจำลองคำขอ HTTP แบบ async ที่ช้า
A.Grandt

14
ถ้าโดย "การทดสอบ" คุณหมายถึงการทดสอบหน่วย: กรอบการทดสอบของคุณควรมีวิธีในการเรียกใช้การทดสอบแบบอะซิงโครนัส หากคุณหมายถึงการทดสอบด้วยตนเอง: แท็บเครือข่ายของ Chrome มีแบบเลื่อนลงการควบคุมปริมาณเพื่อจำลองคำขอที่ช้า
Joseph Silber

1
จะเกิดอะไรขึ้นถ้าฉันพัฒนาส่วนขยายของโครเมี่ยมและค่าที่ประเมินล่าสุดในสคริปต์แบบฉีดควรให้ผลลัพธ์กับฉัน และฉันต้องการความล่าช้าบ้างไหม?
mirek

184

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

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}

ด้วยการดำเนินการในรูปแบบ:

console.log('before');
wait(7000);  //7 seconds in milliseconds
console.log('after');

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


7
สิ่งนี้จะไม่หยุดการเรียกใช้จาวาสคริปต์
เทอร์รี่หลิน

23
@TerryLin ลองใช้งาน
Mic

6
โดยพื้นฐานแล้วคุณเสียเวลาของ CPU นั่นไม่ใช่การรอเนื่องจากคุณไม่ได้ใส่เธรดเข้าสู่โหมดสลีปเพื่อให้ตัวประมวลผลหลักโฟกัสในงานอื่น ๆ
Kyordhel

6
@Gzork Thread sleep เป็นวิธีเดียวที่จะใช้ฟังก์ชั่นการรอและน่าเสียดายที่มันไม่สามารถใช้ได้ในบริบทของจาวาสคริปต์ฝั่งไคลเอ็นต์ อย่างไรก็ตามหากคุณคิดว่างานอะซิงโครนัสอื่น ๆ ในไคลเอ็นต์จะเสร็จสมบูรณ์ในขณะที่ทำงานอยู่คุณจะไม่ได้ทำการทดสอบ แม้ว่าฉันจะใช้มันในเธรดหลักฉันรวบรวมซอแสดงให้เห็นว่าแม้ว่าสิ่งนี้ถูกเรียกผ่าน setTimeout ในตอนแรกมันยังคงขัดจังหวะกิจกรรม async อื่น ๆjsfiddle.net/souv51v3/1 - คุณจะพบว่า หน้าต่าง JSFiddle จะไม่ตอบสนองขณะทำเสร็จ
Mic

1
วิธีการอันน่ากลัว IMHO - hogs CPU ขณะที่ "sleep" วิธีการนอนหลับที่ถูกต้องคือผ่าน async / รอคอยคำตอบนี้stackoverflow.com/questions/951021/หรือของเอเตียน
David Simic

162

นี่คือวิธีการแก้ปัญหาโดยใช้ไวยากรณ์ใหม่/ รอคอย

ตรวจสอบให้แน่ใจว่าได้ตรวจสอบการสนับสนุนเบราว์เซอร์เนื่องจากเป็นคุณลักษณะใหม่ที่นำมาใช้กับ ECMAScript 6

ฟังก์ชั่นยูทิลิตี้:

const delay = ms => new Promise(res => setTimeout(res, ms));

การใช้งาน:

const yourFunction = async () => {
  await delay(5000);
  console.log("Waited 5s");

  await delay(5000);
  console.log("Waited an additional 5s");
};

ข้อดีของวิธีนี้คือทำให้โค้ดของคุณดูและทำงานเหมือนโค้ดซิงโครนัส


ไม่จำเป็นต้องใช้ ECMAScript 6: ถ้าคุณใช้สัญญาแล้วทำการโหลด async และเพียงแค่ต้องการเลียนแบบส่วนหนึ่งของ chain ที่ใช้เวลานานคุณสามารถเพิ่มฟังก์ชัน wait () ใน chain
Dovev Hefetz

2
นี่เป็นคำตอบที่ดีที่สุดสำหรับไวยากรณ์ใหม่ ฉันมีปัญหากับการใช้โซลูชัน wait () ด้านบน
pianoman102

37

ใช้ฟังก์ชั่นการหน่วงเวลาเช่นนี้:

var delay = ( function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
})();

การใช้งาน:

delay(function(){
    // do stuff
}, 5000 ); // end delay

เครดิต: วิธีการหน่วงเวลาตัวจัดการ. keyup () จนกว่าผู้ใช้จะหยุดพิมพ์


36

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

ตัวอย่างเช่น:

function stateChange(newState) {
    setTimeout(function(){
        if(newState == -1){alert('VIDEO HAS STOPPED');}
    }, 5000);
}

แต่ถ้าคุณมีรหัสเช่นนี้:

stateChange(-1);
console.log("Hello");

console.log()คำสั่งจะทำงานทันที มันจะไม่รอจนกว่าจะหมดเวลาในการstateChange()ทำงาน คุณไม่สามารถหยุดการประมวลผลจาวาสคริปต์ไว้ชั่วคราวได้ตามระยะเวลาที่กำหนดไว้

รหัสใด ๆ ที่คุณต้องการเรียกใช้การหน่วงเวลาต้องอยู่ภายในsetTimeout()ฟังก์ชันการเรียกกลับ (หรือเรียกจากฟังก์ชันนั้น)

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


31
คุณก็ไม่สามารถหยุดการดำเนินงาน JavaScript เพื่อใช้จำนวนที่กำหนดไว้ของเวลา ฉันคิดว่าคุณหมายความว่าคุณไม่ควรเนื่องจากคุณสามารถ (ถ้าคุณต้องการที่จะแขวนตัวเอง):var t = new Date().getTime(); while (new Date().getTime() < t + millisecondsToLockupBrowser);
โจเซฟ Silber

9
@JosephSilber - โอเคคุณสามารถทำเช่นนั้นได้ แต่ในทางปฏิบัติที่ไม่ทำงานเนื่องจากเบราว์เซอร์จำนวนมากจะใช้กล่องโต้ตอบโดยบอกว่าสคริปต์ไม่ตอบสนองและเป็นประสบการณ์การใช้งานที่แย่มากและไม่ดีสำหรับอายุการใช้งานของแบตเตอรี่ แขวนในขณะที่ทำเช่นนั้นและ ... มันจะไม่ดี
jfriend00

12
ดีของหลักสูตรที่จะน่ากลัวและไม่มีใครควรเคยเคยเคยเคยเคยเคยทำอย่างนั้น ฉันเพียงแค่ไม่สามารถต้านทานภายในของฉัน"ความจริง" ขอโทษ
Joseph Silber

31

หากคุณอยู่ในฟังก์ชัน asyncคุณสามารถทำได้ในบรรทัดเดียว:

console.log(1);
await new Promise(resolve => setTimeout(resolve, 3000)); // 3 sec
console.log(2);

โปรดสังเกตว่าหากเป้าหมายคือ NodeJS จะมีประสิทธิภาพมากขึ้นในการใช้สิ่งนี้ (มันเป็นฟังก์ชั่น setTimeout ที่กำหนดไว้ล่วงหน้าที่ได้รับการกำหนดไว้ล่วงหน้า):

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec

ความแตกต่างระหว่างการใช้งานทั้งสองคืออะไร?
EAzevedo

1
ปัจจุบันไม่มีความแตกต่าง แต่ถ้า ณ จุดใดจุดหนึ่งจะตัดสินใจที่จะทำให้เร็วขึ้น / ปลอดภัย / มีประสิทธิภาพมากขึ้นคุณจะใช้โหนดรุ่น js ล่วงหน้า แม้ว่าความพร้อมในการอ่านมีแนวโน้มที่จะเป็นปัจจัยสำคัญสำหรับคนส่วนใหญ่ซึ่งในกรณีนี้คุณควรใช้วิธีแรกดีกว่า
Shl

ขอบคุณ. คำตอบของคุณแก้ปัญหาที่ฉันเผชิญมาสามวันแล้ว ขอบคุณ
EAzevedo


7

วิธีที่ดีที่สุดในการสร้างฟังก์ชั่นเช่นนี้รอเป็นมิลลิวินาทีฟังก์ชั่นนี้จะรอเป็นมิลลิวินาทีที่ระบุในอาร์กิวเมนต์:

function waitSeconds(iMilliSeconds) {
    var counter= 0
        , start = new Date().getTime()
        , end = 0;
    while (counter < iMilliSeconds) {
        end = new Date().getTime();
        counter = end - start;
    }
}


3

ตามคำตอบของโจเซฟซิลเบอร์ฉันจะทำอย่างนั้นทั่วไปอีกเล็กน้อย

คุณจะมีฟังก์ชั่นของคุณ (ลองสร้างตามคำถาม):

function videoStopped(newState){
   if (newState == -1) {
       alert('VIDEO HAS STOPPED');
   }
}

และคุณอาจมีฟังก์ชั่นรอ:

function wait(milliseconds, foo, arg){
    setTimeout(function () {
        foo(arg); // will be executed after the specified time
    }, milliseconds);
}

ในตอนท้ายคุณจะมี:

wait(5000, videoStopped, newState);

นั่นเป็นวิธีแก้ปัญหาฉันไม่อยากใช้อาร์กิวเมนต์ในฟังก์ชั่นการรอ (มีเพียงfoo();แทนที่จะเป็นfoo(arg);) แต่นั่นเป็นตัวอย่าง


3

โซลูชันนี้มาจากเอกสารของ React Native สำหรับการควบคุมการรีเฟรช :

function wait(timeout) {
    return new Promise(resolve => {
        setTimeout(resolve, timeout);
    });
}

เพื่อนำไปใช้กับคำถามของ OP คุณสามารถใช้ฟังก์ชันนี้ในการประสานงานกับawait:

await wait(5000);
if (newState == -1) {
    alert('Done');
}

1

คุณสามารถเพิ่มความล่าช้าโดยทำการเปลี่ยนแปลงเล็กน้อยในฟังก์ชั่นของคุณ (async และรอ)

const add5SecondsDelay = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('5 seconds');
    }, 50000);
  });
}

async function asyncFunctionCall() {

  console.log("stpe-1"); 
  const result = await add5SecondsDelay ();
  console.log("step-2 after 5 seconds delay"); 

}

asyncFunctionCall();


-2

สร้างฟังก์ชั่น Js ใหม่

function sleep(delay) {
        var start = new Date().getTime();
        while (new Date().getTime() < start + delay);
      }

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

####Some code
 sleep(1000);
####Next line

3
นั่นจะกินทรัพยากรมากเกินไป
awavi

-2

ฉันใช้เพื่อเรียกใช้เกมพีซีจาก edge หรือ IE และมันก็ปิดตัวเอง IE Edge หลังจาก 7 วินาที

Firefox และ Google Chrome ไม่สามารถใช้เพื่อเริ่มเกมด้วยวิธีนี้

<html<body>
<a href="E:\game\game.exe" name="game" onmouseout="waitclose(7000);"> game
<img src="game.jpg" width="100%" height="97%" ></a>
<script>
function waitclose(ms){
 var start = new Date().getTime();var end=start;
 while(end < start + ms) {end = new Date().getTime();}
window.open('', '_self', ''); window.close();
}
</script>
</body></html>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.