Câu trả lời:
Bạn có thể sử dụng setTimeout
để đạt được hiệu quả tương tự:
var a = 1 + 3;
var b;
setTimeout(function() {
b = a + 4;
}, (3 * 1000));
Điều này không thực sự 'ngủ' JavaScript, nó chỉ thực thi chức năng được truyền đến setTimeout
sau một khoảng thời gian nhất định (được chỉ định bằng mili giây). Mặc dù có thể viết hàm ngủ cho JavaScript, tốt nhất nên sử dụng setTimeout
nếu có thể vì nó không đóng băng mọi thứ trong suốt thời gian ngủ.
Trong trường hợp bạn thực sự cần sleep()
chỉ để kiểm tra một cái gì đó. Nhưng hãy lưu ý rằng nó sẽ bị sập trình duyệt hầu hết thời gian trong khi gỡ lỗi - có lẽ đó là lý do tại sao bạn cần nó. Trong chế độ sản xuất, tôi sẽ nhận xét chức năng này.
function pauseBrowser(millis) {
var date = Date.now();
var curDate = null;
do {
curDate = Date.now();
} while (curDate-date < millis);
}
Không sử dụng new Date()
trong vòng lặp, trừ khi bạn muốn lãng phí bộ nhớ, năng lượng xử lý, pin và có thể là tuổi thọ của thiết bị.
Phiên bản ECMAScript 6, sử dụng các trình tạo có năng suất để "chặn mã":
Bởi vì câu hỏi ban đầu đã được đăng bảy năm trước, tôi không buồn trả lời với mã chính xác, bởi vì nó quá dễ và đã được trả lời. Điều này sẽ giúp trong các vấn đề phức tạp hơn, như nếu bạn cần ít nhất hai giấc ngủ hoặc nếu bạn đang dự định thực hiện chuỗi thực hiện không đồng bộ. Hãy sửa đổi nó để phù hợp với nhu cầu của bạn.
let sleeptime = 100
function* clock()
{
let i = 0
while( i <= 10000 )
{
i++
console.log(i); // actually, just do stuff you wanna do.
setTimeout(
()=>
{
clk.next()
}
, sleeptime
)
yield
}
}
let clk = clock()
clk.next()
Bạn cũng có thể xâu chuỗi các sự kiện thông qua Lời hứa :
function sleep(ms)
{
return(
new Promise(function(resolve, reject)
{
setTimeout(function() { resolve(); }, ms);
})
);
}
sleep(1000).then(function()
{
console.log('1')
sleep(1000).then(function()
{
console.log('2')
})
})
Hoặc đơn giản hơn nhiều và một cách ít ưa thích hơn sẽ là
function sleep(ms, f)
{
return(
setTimeout(f, ms)
)
}
sleep(500, function()
{
console.log('1')
sleep(500, function()
{
console.log('2')
})
})
console.log('Event chain launched')
Nếu bạn chỉ chờ đợi một số điều kiện xảy ra, bạn có thể đợi như thế này
function waitTill(condition, thenDo)
{
if (eval(condition))
{
thenDo()
return
}
setTimeout(
() =>
{
waitTill(condition, thenDo)
}
,
1
)
}
x=0
waitTill(
'x>2 || x==1'
,
() =>
{
console.log("Conditions met!")
}
)
// Simulating the change
setTimeout(
() =>
{
x = 1
}
,
1000
)
Safari, Firefox và Node.js mới nhất hiện cũng hỗ trợ async / await / hứa hẹn.
(Kể từ 1/2017, được hỗ trợ trên Chrome, nhưng không có trên Safari, Internet Explorer, Firefox, Node.js)
'use strict';
function sleep(ms) {
return new Promise(res => setTimeout(res, ms));
}
let myAsyncFunc = async function() {
console.log('Sleeping');
await sleep(3000);
console.log('Done');
}
myAsyncFunc();
JavaScript đã phát triển kể từ khi câu hỏi này được hỏi và hiện có các hàm tạo và async / await / Promise mới đang được triển khai. Bên dưới có hai giải pháp, một giải pháp có chức năng tạo sẽ hoạt động trên tất cả các trình duyệt hiện đại và một giải pháp khác, sử dụng async / await mới chưa được hỗ trợ ở mọi nơi.
'use strict';
let myAsync = (g) => (...args) => {
let f, res = () => f.next(),
sleep = (ms) => setTimeout(res, ms);
f = g.apply({sleep}, args); f.next();
};
let myAsyncFunc = myAsync(function*() {
let {sleep} = this;
console.log("Sleeping");
yield sleep(3000);
console.log("Done");
});
myAsyncFunc();
Hãy chú ý đến thực tế là cả hai giải pháp này đều không đồng bộ về bản chất. Điều này có nghĩa là myAsyncFunc (trong cả hai trường hợp) sẽ trở lại trong khi ngủ.
Điều quan trọng cần lưu ý là câu hỏi này khác với phiên bản JavaScript của ngủ () là gì? trong đó người yêu cầu yêu cầu ngủ thực (không thực hiện mã nào khác trong quy trình) thay vì trì hoãn giữa các hành động.
let co = gen => (...args) => { let iter = gen(...args); let resume = () => new Promise((resolve, reject) => { let result = iter.next(); if (result.done) resolve(result.value); else Promise.resolve(result.value).then(resume).then(resolve, reject); }); return resume(); };
sẽ cho phép bạn let asyncAdd = co(function* (a, b) { console.log('Sleeping'); yield sleep(3000); console.log('Done'); return a + b; }); asyncAdd(3, 4).then(console.log);
sử dụng định nghĩa sleep()
từ khối mã thứ hai của bạn.
Nếu bạn muốn các hàm ít cồng kềnh hơn setTimeout
và setInterval
, bạn có thể bọc chúng trong các hàm chỉ đảo ngược thứ tự của các đối số và đặt cho chúng các tên hay:
function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }
Phiên bản CoffeeScript:
after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms
Sau đó, bạn có thể sử dụng chúng độc đáo với các chức năng ẩn danh:
after(1000, function(){
console.log("it's been a second");
after(1000, function(){
console.log("it's been another second");
});
});
Bây giờ nó đọc dễ dàng là "sau N mili giây, ..." (hoặc "mỗi N mili giây, ...")
Một cách khác để làm điều đó là sử dụng Promise và setTimeout (lưu ý rằng bạn cần phải ở trong một hàm và đặt nó không đồng bộ với từ khóa async):
async yourAsynchronousFunction () {
var a = 1+3;
await new Promise( (resolve) => {
setTimeout( () => { resolve(); }, 3000);
}
var b = a + 4;
}
Đây là một cách rất đơn giản để làm điều đó "cảm thấy" giống như một giấc ngủ / tạm dừng đồng bộ, nhưng là mã không đồng bộ js hợp pháp.
// Create a simple pause function
const pause = (timeoutMsec) => new Promise(resolve => setTimeout(resolve,timeoutMsec))
async function main () {
console.log('starting');
// Call with await to pause. Note that the main function is declared asyc
await pause(3*1000)
console.log('done');
}
Có một số cách để giải quyết vấn đề này. Nếu chúng ta sử dụng setTimeout
chức năng, hãy làm quen với nó trước.
Hàm này có ba tham số: function
hoặc code
, delay
(tính bằng mili giây) và parameters
. Vì tham số chức năng hoặc mã là bắt buộc, những cái khác là tùy chọn. Khi bạn chưa nhập độ trễ , nó sẽ được đặt thành không.
Để biết thêm chi tiết về việc setTimeout()
đi đến liên kết này .
Phiên bản đơn giản hóa:
var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(function(){
b = a + 4;
console.log('b = ' + b);
}, 1000);
đầu ra:
a = 4
24 -> Số nhận dạng của danh sách thời gian chờ hoạt động
b = 8
Sử dụng thông số vượt qua:
var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(myFunction, 1000, a);
function myFunction(a)
{
var b = a + 4;
console.log('b = ' + b);
}
đầu ra:
a = 4
25 -> Số nhận dạng của danh sách thời gian chờ hoạt động
b = 8
Hỗ trợ trình duyệt:
Chrome Firefox Edge Safari Opera 1.0 1.0 4.0 1.0 4.0
Đây là mô hình của tôi cho thấy cách "ngủ" hoặc "DoEvents" trong javascript bằng cách sử dụng chức năng tạo (ES6). Mã nhận xét:
<html>
<head>
<script>
"use strict"; // always
// Based on post by www-0av-Com /programming/3143928
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
var divelt, time0, globaln = 0; // global variables
var MainGenObj = Main(); // generator object = generator function()
window.onload = function() {
divelt = document.getElementsByTagName("body")[0]; // for addline()
addline("typeof Main: " + typeof Main);
addline("typeof MainDriver: " + typeof MainDriver);
addline("typeof MainGenObj: " + typeof MainGenObj);
time0 = new Date().valueOf(); // starting time ms
MainDriver(); // do all parts of Main()
}
function* Main() { // this is "Main" -- generator function -- code goes here
// could be loops, or inline, like this:
addline("Part A, time: " + time() + ", " + ++globaln); // part A
yield 2000; // yield for 2000 ms (like sleep)
addline("Part B, time: " + time() + ", " + ++globaln); // part B
yield 3000; // yield for 3000 ms (or like DoEvents)
addline("Part Z, time: " + time() + ", " + ++globaln); // part Z (last part)
addline("End, time: " + time());
}
function MainDriver() { // this does all parts, with delays
var obj = MainGenObj.next(); // executes the next (or first) part of Main()
if (obj.done == false) { // if "yield"ed, this will be false
setTimeout(MainDriver, obj.value); // repeat after delay
}
}
function time() { // seconds from time0 to 3 decimal places
var ret = ((new Date().valueOf() - time0)/1000).toString();
if (ret.indexOf(".") == -1) ret += ".000";
while (ret.indexOf(".") >= ret.length-3) ret += "0";
return ret;
}
function addline(what) { // output
divelt.innerHTML += "<br />\n" + what;
}
</script>
</head>
<body>
<button onclick="alert('I\'m alive!');"> Hit me to see if I'm alive </button>
</body>
</html>
Hãy thử chức năng này:
const delay = (ms, cb) => setTimeout(cb, ms)
Đây là cách bạn sử dụng nó:
console.log("Waiting for 5 seconds.")
delay(5000, function() {
console.log("Finished waiting for 5 seconds.")
})
Hoặc đi theo kiểu hứa hẹn:
const delay = ms => new Promise(resolve => {
setTimeout(resolve, ms)
})
Đây là một bản demo .