Đợi 5 giây trước khi thực hiện dòng tiếp theo


313

Hàm này bên dưới không hoạt động như tôi muốn; là một người mới làm quen với JS Tôi không thể hiểu tại sao.

Tôi cần nó để chờ 5 giây trước khi kiểm tra xem newState-1.

Hiện tại, nó không chờ đợi, nó chỉ kiểm tra ngay lập tức.

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

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

Câu trả lời:


323

Bạn phải đặt mã của mình vào chức năng gọi lại mà bạn cung cấp cho setTimeout:

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

Bất kỳ mã nào khác sẽ thực thi ngay lập tức.


4
Vấn đề chính là trong một số trường hợp (cụ thể là thử nghiệm) điều này là không đủ. Điều gì xảy ra nếu bạn cần ngủ trong 500ms trước khi trở về từ chức năng để mô phỏng yêu cầu http không đồng bộ chậm ?
A.Grandt

14
Nếu bằng cách "kiểm tra", bạn có nghĩa là kiểm tra đơn vị: khung kiểm tra của bạn sẽ có cách để chạy thử nghiệm không đồng bộ. Nếu bạn muốn kiểm tra thủ công: tab Mạng của Chrome có trình đơn thả xuống Throttling để mô phỏng các yêu cầu chậm.
Joseph Silber

1
Điều gì xảy ra nếu tôi phát triển tiện ích chrome và giá trị được đánh giá cuối cùng trong tập lệnh được chèn sẽ cho tôi kết quả; và tôi cần một số chậm trễ?
mirek

184

Bạn thực sự không nên làm điều này , việc sử dụng đúng thời gian chờ là công cụ phù hợp cho vấn đề của OP và bất kỳ dịp nào khác mà bạn chỉ muốn chạy một cái gì đó sau một khoảng thời gian. Joseph Silber đã chứng minh điều đó tốt trong câu trả lời của mình. Tuy nhiên, nếu trong một số trường hợp không sản xuất bạn thực sự muốn treo chủ đề chính trong một khoảng thời gian, điều này sẽ làm điều đó.

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

Với việc thực hiện theo mẫu:

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

Tôi đã đến đây vì tôi đang xây dựng một trường hợp thử nghiệm đơn giản để giải trình tự hỗn hợp các hoạt động không đồng bộ xung quanh các hoạt động chặn chạy dài (tức là thao tác DOM đắt tiền) và đây là hoạt động chặn mô phỏng của tôi. Nó phù hợp với công việc đó, vì vậy tôi nghĩ rằng tôi đã đăng nó cho bất kỳ ai khác đến đây với trường hợp sử dụng tương tự. Mặc dù vậy, nó đang tạo một đối tượng Date () trong một vòng lặp while, điều này có thể sẽ áp đảo GC nếu nó chạy đủ lâu. Nhưng tôi không thể nhấn mạnh đủ, điều này chỉ phù hợp để thử nghiệm, để xây dựng bất kỳ chức năng thực tế nào bạn nên tham khảo câu trả lời của Joseph Silber.


7
Điều này sẽ không dừng thực thi javascript.
Terry Lin

23
@TerryLin Hãy thử chạy nó.
Mic

6
Vì vậy, về cơ bản bạn đang lãng phí thời gian CPU. Đó không phải là chờ đợi vì bạn không đặt luồng vào chế độ ngủ cho phép bộ xử lý chính tập trung vào các tác vụ khác.
Kyordhel

6
@Gzork Thread ngủ chỉ là một cách để thực hiện chức năng chờ và rất tiếc là không có sẵn trong ngữ cảnh của javascript phía máy khách. Tuy nhiên, nếu bạn nghĩ rằng các tác vụ không đồng bộ khác trong máy khách sẽ được hoàn thành trong khi nó đang chạy, thì rõ ràng bạn đã không kiểm tra nó. Mặc dù tôi sẽ sử dụng nó trong luồng chính, tôi kết hợp một câu đố minh họa cách ngay cả khi điều này được gọi thông qua setTimeout ở vị trí đầu tiên, nó vẫn làm gián đoạn các sự kiện async khác jsfiddle.net/souv51v3/1 - bạn sẽ tìm thấy ngay cả Cửa sổ JSFiddle tự nó trở nên không phản hồi trong khi nó hoàn thành.
Mic

1
Giải pháp khủng khiếp IMHO - cuốc CPU trong khi nó đang "ngủ". Cách ngủ đúng là thông qua async / await ala câu trả lời này stackoverflow.com/questions/951021/ mẹo hoặc Etienne.
David Simic

163

Đây là một giải pháp sử dụng cú pháp async / await mới .

Hãy chắc chắn kiểm tra hỗ trợ trình duyệt vì đây là một tính năng mới được giới thiệu với ECMAScript 6.

Chức năng tiện ích:

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

Sử dụng:

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

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

Ưu điểm của phương pháp này là nó làm cho mã của bạn trông và hoạt động giống như mã đồng bộ.


Không cần ECMAScript 6: Nếu bạn đang sử dụng các lời hứa đã thực hiện tải async và chỉ muốn bắt chước một phần của chuỗi mất nhiều thời gian, bạn có thể thêm hàm Wait () này vào chuỗi.
Dovev Hefetz

2
Đây thực sự là câu trả lời tốt nhất với cú pháp mới. Tôi gặp vấn đề với việc sử dụng giải pháp Wait () ở trên.
pianoman102


36

Bạn không nên cố gắng tạm dừng 5 giây trong javascript. Nó không hoạt động theo cách đó. Bạn có thể lên lịch cho chức năng mã để chạy 5 giây kể từ bây giờ, nhưng bạn phải đặt mã mà bạn muốn chạy sau đó vào một chức năng và phần còn lại của mã sau chức năng đó sẽ tiếp tục chạy ngay lập tức.

Ví dụ:

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

Nhưng, nếu bạn có mã như thế này:

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

Các console.log()tuyên bố sẽ chạy ngay lập tức. Nó sẽ không đợi cho đến khi hết thời gian chờ trong stateChange()chức năng. Bạn không thể chỉ tạm dừng thực thi javascript trong một khoảng thời gian xác định trước.

Thay vào đó, bất kỳ mã nào bạn muốn chạy độ trễ phải nằm trong setTimeout()hàm gọi lại (hoặc được gọi từ hàm đó).

Nếu bạn đã cố gắng "tạm dừng" bằng cách lặp, thì về cơ bản, bạn sẽ "treo" trình thông dịch Javascript trong một khoảng thời gian. Vì Javascript chỉ chạy mã của bạn trong một luồng duy nhất, khi bạn lặp không có gì khác có thể chạy (không có trình xử lý sự kiện nào khác có thể được gọi). Vì vậy, việc lặp vòng chờ đợi một số biến thay đổi sẽ không bao giờ hoạt động vì không có mã nào khác có thể chạy để thay đổi biến đó.


31
Bạn không thể chỉ tạm dừng thực thi javascript trong một khoảng thời gian xác định trước . Tôi nghĩ bạn có nghĩa là bạn không nên, vì bạn có thể (nếu bạn muốn treo cổ tự tử):var t = new Date().getTime(); while (new Date().getTime() < t + millisecondsToLockupBrowser);
Joseph Silber

9
@JosephSilber - Tốt thôi, bạn có thể làm điều đó, nhưng trong thực tế, nó không hoạt động vì nhiều trình duyệt sẽ đưa ra một hộp thoại nói rằng tập lệnh đã không phản hồi VÀ đó là trải nghiệm người dùng khủng khiếp và nó rất tệ cho thời lượng pin và trang này treo trong khi làm như vậy và ... Điều đó sẽ là xấu.
jfriend00

12
Tất nhiên điều đó sẽ rất kinh khủng, và không ai từng có bao giờ làm điều đó. Tôi không thể cưỡng lại "thực tế" bên trong của mình . Lấy làm tiếc.
Joseph Silber

31

Nếu bạn đang ở trong chức năng không đồng bộ, bạn chỉ cần thực hiện trong một dòng:

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

Lưu ý , nếu mục tiêu là NodeJS, việc sử dụng này sẽ hiệu quả hơn (đó là chức năng setTimeout được xác định trước):

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

Sự khác biệt giữa hai thực hiện là gì?
EAzevedo

1
Hiện tại, không có sự khác biệt. Nhưng nếu tại một thời điểm nào đó, nút sẽ quyết định làm cho nó nhanh hơn / an toàn hơn / hiệu quả hơn thì bạn sẽ sử dụng phiên bản nút js trả trước. Mặc dù khả năng sẵn sàng có nhiều khả năng là yếu tố chính đối với hầu hết mọi người, nhưng trong trường hợp đó, bạn nên sử dụng cách đầu tiên tốt hơn.
Shl

Cảm ơn bạn. Câu trả lời của bạn đã giải quyết một vấn đề tôi đã phải đối mặt trong ba ngày rồi. Cảm ơn.
EAzevedo

8

Thử cái này:

//the code will execute in 1 3 5 7 9 seconds later
function exec() {
    for(var i=0;i<5;i++) {
        setTimeout(function() {
            console.log(new Date());   //It's you code
        },(i+i+1)*1000);
    }
}

7

Cách tốt nhất để tạo một hàm như thế này để chờ tính bằng mili giây, hàm này sẽ đợi mili giây được cung cấp trong đối số:

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


3

Dựa trên câu trả lời của Joseph Silber , tôi sẽ làm như thế, chung chung hơn một chút.

Bạn sẽ có chức năng của mình (hãy tạo một cái dựa trên câu hỏi):

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

Và bạn có thể có chức năng chờ:

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

Cuối cùng, bạn sẽ có:

wait(5000, videoStopped, newState);

Đó là một giải pháp, tôi không muốn sử dụng các đối số trong hàm chờ (chỉ có foo();thay vì foo(arg);) mà là ví dụ.


3

Giải pháp này xuất phát từ tài liệu của React Native để kiểm soát làm mới :

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

Để áp dụng điều này cho câu hỏi của OP, bạn có thể sử dụng chức năng này phối hợp với await:

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

1

Bạn có thể thêm độ trễ bằng cách thực hiện các thay đổi nhỏ cho chức năng của mình (không đồng bộ và chờ đợi).

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

sử dụng angularjs:

$timeout(function(){
if(yourvariable===-1){
doSomeThingAfter5Seconds();
}
},5000)

-2

Tạo chức năng Js mới

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

Gọi hàm khi bạn muốn trì hoãn thực hiện. Sử dụng mili giây trong int cho giá trị độ trễ.

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

3
Điều đó sẽ tiêu tốn quá nhiều tài nguyên.
awavi

-2

Tôi đã sử dụng nó để chạy các trò chơi PC từ edge hoặc IE. Và nó tự đóng IE Edge sau 7 giây.

Firefox và Google Chrome không thể được sử dụng để bắt đầu trò chơi theo cách này.

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.