01/10/2018, 15:42

Cho e hỏi Vòng lặp trong javascript

Em có code như này do e viết

<link rel="stylesheet" href="https://vip.pro.vn/bootstrap/css/bootstrap.min.css">
<script src="https://vip.pro.vn/plugins/jQuery/jquery-3.1.1.min.js"></script>
<script src="https://vip.pro.vn/bootstrap/js/bootstrap.min.js"></script>
<div id="total"></div>
<div id="running"></div>
<textarea class="form-control" rows="10" id="result"></textarea>
<script>
    let number = [1,2,3,4,5];
    $('#total').text('Total: '+ number.length);
    for(let i = 0; i < number.length; i++){
        $('#running').text('Running: '+(i+1));
        for(let j = 0; j < 10; j++){
            setTimeout(function(){
                $('#result').append(j+"
");
            }, 1000);
        }
    }
</script>

em muốn khi chạy thì div#running sẽ hiện lần lượt từ 1-5, mỗi một lần thì mỗi giây sẽ hiện từ 0-9 vào textarea (tức là phải mất 9 giây để hiện hết từ 0-9 vào textarea).

nhưng mà khi chạy là div#running nó lại gán luôn đến 5 và textarea nó ko chạy theo thứ tự mỗi giây 1 số mà in ra luôn 1 lần.

ai giúp em sửa lại code dc ko ạ

*grab popcorn* viết 17:53 ngày 01/10/2018

Tại vì bạn nghĩ là setTimeout khi chờ 1s là nó sẽ chờ 1s.
Nhưng không phải vậy. Nó chạy tiếp. Thế nên bạn nên chỉnh tgian settimeout cách nhau mỗi s

setTimeout(function() {
    $('#running').text('Running: ' + (i + 1));
    $('#result').append(j + "\n");
}, 1000 * (i + 1));
xFerghost viết 17:43 ngày 01/10/2018

Có bài tương tự đây

Uhm, thì nếu như làm công việc sync để sleep thì chắc chắn nó phải chiếm tài nguyên và hệ thống phải đứng chờ rồi, tại lúc nãy mình không hiểu rõ ý "đơ" của bạn, ^^. Còn về hàm setTimeout thì nó là callback function nên chắc chắn là async rồi. Javascript ưu tiên các hàm xử lý async mà :D.

*grab popcorn* viết 17:45 ngày 01/10/2018

Thì bạn chỉnh code trên là được.
Ở phần thời gian ấy :3

Duy Hoàng viết 17:48 ngày 01/10/2018

hic, em chạy thì ở div#running nó vẫn ra số 5 luôn (đang chạy chỉ số thứ 5 trong mảng), còn textarea thì ra 1 phát từ 0-9 chứ ko fai mỗi giây ra một số ạ

đây ạ https://vip.pro.vn/test.php

Duy Hoàng viết 17:48 ngày 01/10/2018

có khi nào phải dùng đến 2 setTimeout ở mỗi vòng lặp ko nhỉ

*grab popcorn* viết 17:50 ngày 01/10/2018

Đúng rồi :3
Bây giờ có 5 lần.
Mỗi lần in 10 phần tử.
Vậy có phải pahafn tử 1 in ra ở giây 1. Thứ 2 in ra 2 …
Vậy tính toán sao mà nó in ra vậy là được.

Gợi ý là i * 10 + j

Duy Hoàng viết 17:49 ngày 01/10/2018

em làm mãi chả đc, viết giúp em được ko ạ :((

Hung viết 17:57 ngày 01/10/2018
let i = 0;
let interval = setInterval(function () {
  if (i == 10)
    return clearInterval(interval);
  $('#result').append(i + "\n");
  i++;
}, 1000);
Duy Hoàng viết 17:46 ngày 01/10/2018

ui trộ ôi chị đáng yêu quá đi :*

Son Tran viết 17:54 ngày 01/10/2018

Mình có ghi chú 2 cách loop async function (trường hợp này là setTimeout) mà mình biết được tại blog cá nhân: https://tbson.info/javascript-promise-loop/
Paste lên đây luôn để mọi người tiện theo dõi

Cách 1: Dùng Coroutine

async function* promises() {
    const _promises = [
        new Promise(resolve => setTimeout(resolve, 1000, 'Case 1')),
        new Promise(resolve => setTimeout(resolve, 5000, 'Case 2')),
        new Promise(resolve => setTimeout(resolve, 100, 'Case 3')),
    ];

    for (let promise of _promises) yield await promise;
}
for await (let result of promises()) {
    console.log(result);
}

Cách 2: Dùng await trong vòng lặp

const promises = [
    new Promise(resolve => setTimeout(resolve, 1000, 'Case 1')),
    new Promise(resolve => setTimeout(resolve, 5000, 'Case 2')),
    new Promise(resolve => setTimeout(resolve, 100, 'Case 3')),
];
for (let result of promises) {
    console.log(await result);
}
Duy Hoàng viết 17:51 ngày 01/10/2018

trước đó có 1 anh code xử lí vấn đề này vẫn sử dụng setTimeout và em test đc như mong đợi, liệu nên sử dụng cái nào ạ hihi

Son Tran viết 17:44 ngày 01/10/2018

Việc đó tuỳ vào thói quen và sở thích của bạn thôi.
Nên chọn cách nào bạn thấy trực quan và dễ hiểu nhất để tiện cho việc bảo trì sau này.

Bài liên quan
0