Avatar
1
Trần Quốc Đạt Beginner
Promise có bất đồng bộ không?
Hello anh! Em có đọc qua Bài viết về Single thread. Bài chia sẻ rất hay, nó làm em thay đổi cả suy nghĩ trước giờ về Promise.

Trước giờ em cứ nghĩ Promise nó rất thần kì, nó sẽ tự động đưa code bên trong constructor's callback ra một "stack nào đó", đợi đến khi main stack trống, event loop push ngược lại vào main stack như setTimeout, setInterval. hay nói đơn giản là biến code đồng bộ thành bất đồng bộ.

Ví dụ về Promise vẫn có thể xảy ra tình trạng blocking của anh rất hay, nó làm em nhận ra trước giờ mình đã sai về Promise. Nhưng em vẫn còn 1 điều thắc mắc: Promise có phải chỉ là một kiểu dữ liệu "wrapper" cho các service bất đồng bộ khác như WebApi, network,... bla bla và nó được viết thuần JS 100% (có nghĩa Promise vẫn là đồng bộ) không ạ? Lý do thì em nghĩ là để thay đổi cách viết bất đồng bộ bằng callback ngày xưa?

function runWithPromise() {
    let x = 0
    return new Promise(res => {
        while (x++ < 600_000_000);
            console.log(x)

        return res(x)
    })
}

async function runWithAsync() {
    let x = 0
    while (x++ < 600_000_000);
    console.log(x)
    return x
}

runWithAsync()
runWithPromise()

console.log('Finished')

  • Answer
promise async callback
Remain: 5
2 Answers
Avatar
tvd12 Beginner
tvd12 Beginner
The Best Answer
Đầu tiên, các code mà em viết trên javascript sẽ chạy trên main thread em ạ, nên code ở đây em cần viết rất gọn nhẹ. Còn về Promise thì theo anh đoán là nó sẽ giống kiểu đối tượng Future của java, mục tiêu của nó là lắng nghe kết quả trả về từ 1 thread khác. Await cũng sẽ tương đương với Future.get nó sẽ làm block cái thread đang chờ kết quả lại, trong trường hợp này Promise sẽ là đồng bộ. Tuy nhiên nếu em không dùng await thì không phải là đồng bộ mà chỉ có cái hàm callback của promise nó sẽ chạy trên main thread mới bị gọi là đồng bộ thôi em ạ.

Tiếp theo, thực tế sẽ có 2 kiểu viết thư viện em ạ:

  1. Thư viện viết bằng javascript: Sẽ chạy trên main thread
  2. Thư viện viết bằng C/C++ hay các ngôn ngữ native, ví dụ anh đang viết: ezyfox-react-native-client-sdk thì việc xử lý I/O sẽ ở dưới background thread, và các sự kiện hay dữ liệu sẽ chuyển lên main thread thông qua main queue.

Thế nên các thư viện I/O mà em đang dùng cũng sẽ phải viết kiểu đó em ạ, thì mới không làm block main thread và chương trình của em mới hoạt động bình thường được

  • 1
  • Reply
Avatar
Dạ em cảm ơn anh Dũng đã giải đáp, em xin tổng hợp lại những gì mình hiểu xem có đúng không ạ:
  • Promise là một đối tượng, cung cấp một cách thức để "Lắng nghe" kết quả trả về từ 1 thread khác - Cũng như ngày xưa người ta dùng callback để "Lắng nghe".
  • Promise chỉ bất đồng bộ khi trả kết quả về (kết quả truyền vào cho hàm resolve) chứ không phải bất đồng bộ khi execute hàm callback (executor).
  • Tương tự như vậy, await đang "đợi/lắng nghe"  kết quả của Promise chứ không phải đợi executor, bởi executor đã được thực thi trong khi tạo promise rồi.
  • Do vậy dùng Promise thuần để bất đồng bộ một task nặng là sai, do Promise thuần không có khả năng đó. Phải dùng kết hợp với những API hỗ trợ bất đồng bộ khác như setTimeout, setInterval,... để không gây block main thread.
  • 1
  • Reply
Đúng thế em ạ, muốn thực sự có đồng bộ, là em phải code tầng dưới, tầng C/C++ hay các tầng native tương ứng với hệ điều hành em ạ, chứ còn các đối tượng trên javascript chỉ có khả năng gửi sự kiện, dữ liệu từ main thread xuống các luồng ở dưới, và sau đó nhận kết quả ở callback em ạ.

Riêng ý cuối thì chỉ là làm tạm thời không làm block main thread thôi em ạ, chứ cuối cùng thì nó vẫn cứ chạy cái callback ở main thread, và em mà code xử lý nặng ở đây nó vẫn sẽ làm block chương trình. Em có thể thử dụng while(true) ở các hàm callback xem sao nhé.

 –  tvd12 1631999237000