Giải thích về vòng lặp sự kiện JavaScript: Ngăn xếp cuộc gọi, Microtask và bộ hẹn giờ kèm ví dụ

  1. Trang chủ
  2. Blog
  3. Phát triển phần mềm

Phát triển phần mềm

Giải thích về vòng lặp sự kiện JavaScript: Ngăn xếp cuộc gọi, vi nhiệm vụ và bộ tính giờ kèm ví dụ

Tại sao setTimeout bằng 0 vẫn chạy cuối cùng? Làm thế nào một thread có thể xử lý nhiều thứ cùng một lúc? Tìm hiểu cách vòng lặp sự kiện thực sự hoạt động, kiểm tra nó bằng mã chúng tôi đã chạy và giải quyết câu hỏi phỏng vấn cổ điển.

Đọc 9 phút
Giải thích về vòng lặp sự kiện JavaScript: ngăn xếp cuộc gọi, nhiệm vụ vi mô và bộ tính giờ cùng với các ví dụ

Điểm chính

  • JavaScript chạy mã của bạn trên một luồng duy nhất, mỗi lần một đoạn.
  • Khi ngăn xếp cuộc gọi trống, tất cả tác vụ vi mô sẽ chạy trước rồi đến một tác vụ.
  • setTimeout(fn, 0) có nghĩa là “càng sớm càng tốt sau một khoảng thời gian trễ tối thiểu”, không phải “bây giờ”.
  • Công việc đồng bộ kéo dài sẽ chặn mọi thứ, vì vậy hãy chia nhỏ nó ra hoặc chuyển nó cho một nhân viên.

Chạy một vài dòng với setTimeout và một lời hứa, thứ tự đầu ra có thể làm bạn ngạc nhiên. Vòng lặp sự kiện JavaScript giải thích lý do. Đây là cơ chế cho phép ngôn ngữ đơn luồng xử lý bộ tính giờ, cuộc gọi mạng và số lần nhấp mà không bị treo.

Một khi bạn hiểu nó, cả một nhóm lỗi khó hiểu sẽ bắt đầu có ý nghĩa. Chúng tôi đã chạy từng ví dụ trên Node.js 24 và kết quả đầu ra là từ lần chạy đó. Các quy tắc đặt hàng cốt lõi cũng được áp dụng trong các trình duyệt và chúng tôi chỉ ra điểm khác biệt của Node.js. Bạn sẽ thu được nhiều lợi ích hơn từ việc này nếu bạn đã biết kiến ​​thức cơ bản về lời hứa JavaScript.

Tại sao vòng lặp sự kiện tồn tại

JavaScript thực thi mã của bạn trên một luồng chính, do đó chỉ có một đoạn mã chạy tại một thời điểm. Nếu nó chỉ đợi một yêu cầu mạng, một trang sẽ đóng băng cho đến khi có phản hồi.

Vì vậy, JavaScript không chờ đợi. Công việc chậm được chuyển sang môi trường máy chủ, nghĩa là trình duyệt hoặc Node.js, có thể xử lý nó ở chế độ nền. Khi công việc đó kết thúc, một cuộc gọi lại sẽ được đưa vào hàng đợi. Công việc của vòng lặp sự kiện là di chuyển các cuộc gọi lại được xếp hàng đợi vào ngăn xếp khi nó rảnh.

Hãy nghĩ đến một đầu bếp làm việc một mình. Đầu bếp đặt món ăn vào lò nướng và hẹn giờ thay vì nhìn chằm chằm vào nó. Khi đồng hồ reo, nhiệm vụ sẽ được đưa vào danh sách và đầu bếp sẽ thực hiện nó sau khi hoàn thành những gì hiện có trong tay.

Các bộ phận chuyển động

phần Nó làm gì Ví dụ
ngăn xếp cuộc gọi Theo dõi các chức năng hiện đang chạy Mã đồng bộ của bạn
API máy chủ Làm việc bên ngoài mã của bạn Bộ hẹn giờ, fetch, đọc tệp
Hàng đợi nhiệm vụ Giữ các cuộc gọi lại đã sẵn sàng để chạy setTimeout, số nhấp chuột, I/O
Hàng đợi vi nhiệm Giữ các cuộc gọi lại có mức độ ưu tiên cao hơn .then, await, queueMicrotask
Vòng lặp sự kiện Quyết định những gì chạy tiếp theo Chạy liên tục

Nhiệm vụ đôi khi được gọi là nhiệm vụ vĩ mô. Nói đúng ra, có thể có một số nguồn nhiệm vụ và chi tiết chính xác khác nhau giữa các môi trường.

Các quy tắc

  1. Chạy tất cả mã đồng bộ cho đến khi ngăn xếp cuộc gọi trống.
  2. Chạy tất cả vi nhiệm vụ, bao gồm mọi nhiệm vụ mới được thêm vào trong quá trình thực hiện.
  3. Trong trình duyệt, hiển thị bản cập nhật nếu đến hạn.
  4. Lấy một nhiệm vụ từ hàng đợi và chạy nó.
  5. Quay lại bước 2.

Chi tiết quan trọng nhất: tất cả nhiệm vụ vi mô, sau đó là một nhiệm vụ. Hầu hết các câu đố về vòng lặp sự kiện đều được giải bằng cách áp dụng quy tắc duy nhất đó.

Xem thứ tự

console.log("1 sync");
setTimeout(() => console.log("5 timeout"), 0);
Promise.resolve().then(() => console.log("3 promise"));
queueMicrotask(() => console.log("4 microtask"));
console.log("2 sync");

// 1 sync
// 2 sync
// 3 promise
// 4 microtask
// 5 timeout

Đây là những gì đã xảy ra. Hai dòng console.log đồng bộ nên chạy trước. Lệnh gọi lại lời hứa và queueMicrotask đã đi vào hàng đợi vi nhiệm và chúng chạy ngay khi ngăn xếp trống, theo thứ tự chúng được thêm vào. Cuộc gọi lại hẹn giờ phải chờ đến lượt nhiệm vụ, mặc dù độ trễ của nó bằng 0.

Microtask chạy giữa các bộ tính giờ

Sau mỗi tác vụ, hàng đợi vi tác vụ lại được làm trống. Ví dụ này chứng minh điều đó:

setTimeout(() => {
  console.log("timer 1");
  Promise.resolve().then(() => console.log("promise inside timer 1"));
}, 0);
setTimeout(() => console.log("timer 2"), 0);

// timer 1
// promise inside timer 1
// timer 2

Lời hứa được tạo trong bộ tính giờ đầu tiên đã chạy trước bộ tính giờ thứ hai. Các trình duyệt hiện đại và Node.js 11 trở lên hoạt động theo cách này.

Nơi chờ đợi phù hợp

await chia một hàm thành hai. Mọi thứ trước khi chạy đồng bộ và mọi thứ sau khi được lên lịch dưới dạng microtask. Điều này khiến nhiều người ngạc nhiên:

async function task() {
  console.log("A before await");
  await null;
  console.log("C after await");
}

task();
console.log("B after calling task");

// A before await
// B after calling task
// C after await

Chức năng async không khởi động ở chế độ nền. Nó chạy trên cùng một luồng cho đến khi đạt đến luồng đầu tiên await. Điều đó thậm chí còn được áp dụng khi chờ đợi một điều gì đó không phải là một lời hứa thực sự, chẳng hạn như null. Xem Hướng dẫn chờ đợi/không đồng bộ JavaScript của chúng tôi để biết thêm về cú pháp này.

Chặn vòng lặp

Trong khi mã đồng bộ chạy, không có gì khác có thể làm được. Để hiển thị điều này, chúng tôi đặt bộ hẹn giờ trong 0 mili giây, sau đó giữ cho luồng bận trong nửa giây:

const start = Date.now();
setTimeout(() => console.log("timer ran after", Date.now() - start, "ms"), 0);
while (Date.now() - start < 500) {}

// timer ran after about 500 ms

Độ trễ của bộ hẹn giờ là tối thiểu, không phải là sự đảm bảo. Nó chỉ chạy khi ngăn xếp trở nên trống. Trên một trang web, vòng lặp dài như thế này có nghĩa là các lần nhấp chuột không phản hồi và hoạt ảnh sẽ dừng lại. Trên máy chủ, mọi yêu cầu khác đều phải chờ, đó là lý do tại sao một cuộc gọi đồng bộ chậm có thể gây tổn hại cho tất cả người dùng quy trình Node.js.

Các nguyên nhân phổ biến của việc chặn bao gồm các vòng lặp lớn, phân tích cú pháp JSON rất lớn, các hàm tệp đồng bộ như readFileSync trong trình xử lý yêu cầu và các biểu thức chính quy thảm khốc.

Mẹo: Trong Chrome DevTools, bảng Hiệu suất đánh dấu các tác vụ dài hơn 50 mili giây là các tác vụ dài. Đó là một cách nhanh chóng để tìm ra nguyên nhân khiến trang có cảm giác chậm chạp.

Luôn đáp ứng

Đối với công việc nặng nhọc, hãy cho vòng lặp sự kiện một cơ hội để thở. Một cách là thỉnh thoảng tạm dừng đồng hồ hẹn giờ để cho phép các tác vụ khác chạy:

const items = [0, 1, 2, 3, 4];

async function processAll() {
  for (const item of items) {
    if (item === 2) await new Promise((r) => setTimeout(r, 0));
    console.log("item", item);
  }
}

setTimeout(() => console.log("other work gets a turn"), 0);
processAll();

// item 0
// item 1
// other work gets a turn
// item 2
// item 3
// item 4

Đồng hồ hẹn giờ khác chạy ở giữa vì chúng tôi đã thực hiện một nhiệm vụ thực sự. Mã thực sẽ mang lại rất nhiều mục hoặc mili giây. Đối với công việc thực sự nặng về CPU, chẳng hạn như xử lý hình ảnh, hãy sử dụng Web Worker trong trình duyệt hoặc luồng công việc trong Node.js, chạy trên các luồng riêng biệt.

Thiếu nhiệm vụ vi mô

Vì vòng lặp làm trống hoàn toàn hàng đợi vi nhiệm vụ trước khi tiếp tục, nên một vi nhiệm vụ tiếp tục lên lịch nhiều hơn có thể dừng mọi thứ khác. Chúng tôi đã thử nghiệm điều này với 100.000 nhiệm vụ vi mô được xâu chuỗi:

let count = 0;
let timerFired = false;
setTimeout(() => { timerFired = true; }, 0);

function spin() {
  count++;
  if (count < 100000) queueMicrotask(spin);
  else console.log("timer fired during microtasks?", timerFired);
}
queueMicrotask(spin);

// timer fired during microtasks? false

Bộ hẹn giờ không thể chạy cho đến khi tất cả chúng được hoàn thành. Nếu chuỗi đó không bao giờ kết thúc, bộ hẹn giờ sẽ không bao giờ kích hoạt và trong trình duyệt, trang sẽ không bao giờ được sơn lại. Lưu ý rằng việc thực hiện await đối với một lời hứa đã được giải quyết không giúp ích gì ở đây vì nó chỉ bổ sung thêm một vi nhiệm khác. Bạn cần một nhiệm vụ thực tế, chẳng hạn như đồng hồ bấm giờ, để giao việc cho người khác.

Hiển thị trong trình duyệt

Một trình duyệt thường có cơ hội vẽ giữa các tác vụ. Điều đó giải thích một lỗi phổ biến:

spinner.hidden = false;
doHeavyWork();              // blocks the thread
spinner.hidden = true;

Công cụ quay vòng không bao giờ xuất hiện vì trình duyệt không có cơ hội hiển thị giữa các dòng đó. Để khắc phục, hãy để một khung đi qua trước khi công việc nặng bắt đầu hoặc chuyển công việc đó cho một công nhân. Đối với mã thay đổi hình ảnh, requestAnimationFrame chạy ngay trước lần vẽ tiếp theo, điều này khiến nó trở thành công cụ phù hợp cho hoạt ảnh.

Sự khác biệt của Node.js

Node.js có vòng lặp sự kiện riêng với nhiều giai đoạn, bao gồm bộ tính giờ, bỏ phiếu I/O và setImmediate. Nó cũng có process.nextTick, chạy trong hàng đợi riêng của nó. Đây là những gì chúng ta thấy khi chạy chúng từ bên trong một hàm async:

setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
Promise.resolve().then(() => console.log("promise"));

// promise
// nextTick
// immediate
// timeout

Nhiều bài báo nói rằng nextTick luôn đánh bại những lời hứa và đồng hồ bấm giờ sẽ đánh bại setImmediate. Kết quả của chúng tôi cho thấy nó không đơn giản như vậy. Mã của chúng tôi đã chạy trong một microtask, vì vậy hàng đợi lời hứa sẽ được thực hiện trước tiên. Và thứ tự của setTimeout và setImmediate được biết là khác nhau tùy thuộc vào nơi chúng được gọi. Vì vậy, đừng viết mã phụ thuộc vào thứ tự chính xác của chúng. Nếu điều này phải xảy ra sau điều khác, hãy xâu chuỗi chúng một cách rõ ràng.

Bài kiểm tra phỏng vấn

Cố gắng sắp xếp thứ tự trước khi đọc câu trả lời:

console.log("a");
setTimeout(() => console.log("b"), 0);
Promise.resolve().then(() => {
  console.log("c");
  setTimeout(() => console.log("d"), 0);
  Promise.resolve().then(() => console.log("e"));
});
console.log("f");

Cuộc chạy của chúng tôi đã in ra a, f, c, e, b, d. Đây là lý do tại sao:

  1. a và f là đồng bộ nên chúng chạy trước.
  2. Ngăn xếp trống nên các tác vụ vi mô sẽ chạy: c, sau đó là vi tác vụ mới e, trong cùng một vòng.
  3. Bây giờ có một tác vụ: bộ đếm thời gian b, được xếp hàng đầu tiên.
  4. Sau đó, nhiệm vụ tiếp theo: bộ đếm thời gian d, được xếp hàng đợi trong microtask.

Những lỗi thường gặp

  • Suy nghĩ setTimeout là chính xác. Độ trễ chỉ ở mức tối thiểu.
  • Suy nghĩ async nghĩa là một luồng khác. Mã không đồng bộ vẫn chạy trên luồng chính giữa các lần chờ.
  • Sử dụng chế độ ngủ để khắc phục thứ tự. Chờ đợi theo điều kiện thực tế đáng tin cậy hơn nhiều, điều này cũng áp dụng cho kiểm tra không ổn định.
  • Sử dụng forEach với await. Nó không chờ đợi giữa các mục. Xem Các phương thức mảng JavaScript.
  • Thực hiện công việc đồng bộ nặng nề trong trình xử lý máy chủ. Một yêu cầu có thể trì hoãn mọi yêu cầu khác.

Lời kết

Hãy nhớ quy tắc cốt lõi: chạy ngăn xếp cho đến khi trống, chạy tất cả các vi tác vụ, sau đó chạy một tác vụ và lặp lại. Mọi thứ khác đều theo sau nó. Để làm cho nó dễ hiểu, hãy viết phiên bản bài kiểm tra ở trên của riêng bạn, dự đoán kết quả ra giấy và sau đó thực hiện nó. Việc mắc sai lầm và hiểu được lý do tại sao sẽ dạy cho bạn nhiều điều hơn bất kỳ sơ đồ nào.

Câu hỏi thường gặp

Vòng lặp sự kiện trong JavaScript là gì?

Đây là cơ chế chạy các cuộc gọi lại được xếp hàng đợi khi ngăn xếp cuộc gọi trống. Nó cho phép JavaScript đơn luồng xử lý bộ tính giờ, phản hồi đầu vào và mạng mà không bị chặn.

Sự khác biệt giữa microtask và nhiệm vụ là gì?

Các tác vụ vi mô, chẳng hạn như lệnh gọi lại theo lời hứa, đều chạy ngay khi ngăn xếp trống. Các tác vụ, chẳng hạn như bộ tính giờ, chạy lần lượt từng tác vụ và các tác vụ vi mô sẽ được thoát sau mỗi tác vụ.

Tại sao setTimeout bằng 0 không chạy ngay lập tức?

Cuộc gọi lại của nó phải chờ đến lượt nhiệm vụ. Tất cả mã đồng bộ và vi tác vụ đều chạy trước và độ trễ là tối thiểu thay vì thời gian chính xác.

JavaScript có đơn luồng không?

Mã JavaScript chính của bạn chạy trên một luồng. Trình duyệt và Node.js sử dụng các luồng khác cho một số công việc nền và các trình chạy cho phép bạn chạy mã song song.

Chờ đợi có chặn vòng lặp sự kiện không?

Không. chờ đợi chỉ tạm dừng chức năng không đồng bộ đó và mã khác có thể chạy trong thời gian chờ đợi. Tuy nhiên, mã đồng bộ dài trước hoặc sau nó vẫn có thể chặn vòng lặp.

Tiếp tục học hỏi

Làm việc với Stack Quora

Cần trợ giúp về kiểm tra, WordPress hoặc SEO?

Chúng tôi giúp các nhóm phát triển phần mềm tốt hơn và phát triển trang web của họ. Hãy cho chúng tôi biết bạn đang làm gì và chúng tôi sẽ đề xuất bước tiếp theo rõ ràng.

Tiếp tục đọc

Thêm hướng dẫn về thử nghiệm, AI và phát triển hiện đại

Bạn thích bài viết này? Chọn một chủ đề và chuyển ngay sang phần hướng dẫn mới nhất của chúng tôi.

Trí tuệ nhân tạo

Giải thích về ảo giác AI: Tại sao các mô hình ngôn ngữ lại tạo nên mọi thứ và cách giảm thiểu nó

Ảo giác AI đã giải thích: chúng là gì, tại sao mô hình ngôn ngữ tạo ra chúng, các loại phổ biến, cách giảm thiểu chúng bằng cách căn cứ và nhắc nhở …

Đọc bài viết →
DevOps

Giải thích về các biến môi trường: Tệp .env, bí mật và cấu hình được thực hiện đúng

Các biến môi trường được giải thích bằng các ví dụ Python mà chúng tôi đã chạy: đọc và thiết lập chúng, tại sao mọi giá trị đều là một chuỗi, tệp .e…

Đọc bài viết →
Phát triển phần mềm

Giải thích về giới hạn tỷ lệ API: Thuật toán, tiêu đề và xử lý lỗi 429

Giới hạn tốc độ API được giải thích bằng mô phỏng mà chúng tôi đã chạy: nhóm mã thông báo, cửa sổ cố định, cửa sổ trượt, 429 phản hồi, tiêu đề giới …

Đọc bài viết →
Tự động hóa kiểm thử

Chế giễu bằng Python: unittest.mock, patch và những sai lầm khiến bài kiểm tra nói dối

Mô phỏng bằng Python với unittest.mock, đã được thử nghiệm: Mock và return_value, side_effect, vá lỗi nơi sử dụng tên, thông số kỹ thuật và thông số…

Đọc bài viết →
Kiểm thử phần mềm

Giải thích về phạm vi bảo hiểm của mã: Phạm vi tuyến so với chi nhánh và ý nghĩa thực sự 100%

Phạm vi bảo hiểm mã được giải thích bằng cách chạy phạm vi bảo hiểm thực tế: phạm vi bảo hiểm dòng, chi nhánh và điều kiện, đọc báo cáo, lý do tại s…

Đọc bài viết →
Cơ sở dữ liệu & SQL

DELETE vs TRUNCATE vs DROP trong SQL: Sự khác biệt, khôi phục và thời điểm sử dụng mỗi loại

DELETE vs TRUNCATE vs DROP được giải thích bằng SQL đã được thử nghiệm: mỗi loại loại bỏ, khôi phục, kích hoạt, đặt lại danh tính, tốc độ và Postgre…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Giải thích về Chế độ xem SQL: Tạo, sử dụng và tránh những cạm bẫy, kèm theo ví dụ

Chế độ xem SQL được giải thích bằng các truy vấn chúng tôi đã chạy: tạo chế độ xem, kết quả trực tiếp, ẩn cột, hiệu suất, chế độ xem có thể cập nhật…

Đọc bài viết →
Phát triển phần mềm

Giao diện TypeScript so với loại: Sự khác biệt thực sự, được thử nghiệm bằng trình biên dịch

Giao diện TypeScript so với loại, được kiểm tra bằng trình biên dịch thực: cả hai có thể làm gì, chỉ một người có thể làm gì, hợp nhất khai báo, mở …

Đọc bài viết →
Phát triển phần mềm

Giải thích về Python *args và **kwargs: Hàm linh hoạt với ví dụ rõ ràng

Python *args và **kwargs được giải thích bằng mã chúng tôi đã chạy: đóng gói và giải nén, thứ tự tham số, đối số chỉ từ khóa và chỉ vị trí, trình tr…

Đọc bài viết →
Phát triển phần mềm

Hàm Lambda của Python: Cú pháp, cách sử dụng thực tế và khi nào không nên sử dụng chúng

Các hàm lambda của Python được giải thích bằng mã chúng tôi đã chạy: cú pháp, sắp xếp bằng khóa, bản đồ và bộ lọc, các phần đóng, bẫy liên kết muộn …

Đọc bài viết →
Trí tuệ nhân tạo

Đại lý AI là gì? Cách chúng hoạt động, với vòng lặp tác nhân đơn giản, bạn có thể chạy

Tác nhân AI là gì? Hướng dẫn đơn giản về vòng lặp tác nhân, công cụ, bộ nhớ và lan can, với một vòng lặp Python nhỏ mà chúng tôi đã chạy, những rủi …

Đọc bài viết →
DevOps

Giám sát và Khả năng quan sát: Sự khác biệt thực sự, với nhật ký, số liệu và dấu vết

Giải thích về giám sát và khả năng quan sát: lỗi đã biết và chưa biết, nhật ký, số liệu và dấu vết, hướng dẫn về sự cố thanh toán, tín hiệu vàng, Op…

Đọc bài viết →
DevOps

Docker Volumes vs Bind Mounts: Duy trì dữ liệu vùng chứa đúng cách

Giải thích về khối lượng Docker và liên kết gắn kết: tại sao dữ liệu vùng chứa biến mất, khối lượng được đặt tên, liên kết gắn kết, tmpfs, ví dụ về …

Đọc bài viết →
Tự động hóa kiểm thử

TDD vs BDD: Key Differences, One Feature Built Both Ways and When to Use Each

TDD và BDD được giải thích bằng một tính năng giảm giá được xây dựng theo cả hai cách: tái cấu trúc màu đỏ-xanh với mã chúng tôi đã chạy, kịch bản C…

Đọc bài viết →
Kiểm thử phần mềm

Kiểm tra chấp nhận của người dùng (UAT): Quy trình, danh sách kiểm tra và ví dụ thực tế

Giải thích về thử nghiệm chấp nhận của người dùng: ai chạy nó, nó khác với QA như thế nào, quy trình bảy bước, mẫu trường hợp thử nghiệm UAT, danh s…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Giải thích về các giá trị NULL của SQL: IS NULL, COALESCE, NULLIF và những cái bẫy cần tránh

Các giá trị SQL NULL được giải thích bằng các truy vấn chúng tôi đã chạy: logic ba giá trị, IS NULL, COALESCE, NULLIF, cách tổng hợp, kết hợp và sắp…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Câu lệnh SQL CASE WHEN: Cú pháp, ví dụ thực tế và các lỗi thường gặp

TRƯỜNG HỢP SQL KHI được giải thích bằng các truy vấn mà chúng tôi đã chạy: các biểu mẫu đơn giản và được tìm kiếm, thứ tự điều kiện, các thủ thuật S…

Đọc bài viết →
Phát triển phần mềm

JWT là gì? Mã thông báo Web JSON được giải thích bằng một ví dụ hoạt động

JWT là gì? Mã thông báo Web JSON đã giải thích: ba phần, mã thông báo được xây dựng và giả mạo trong mã chúng tôi đã chạy, JWT so với phiên, lưu trữ…

Đọc bài viết →
Phát triển phần mềm

Giải thích về vòng lặp sự kiện JavaScript: Ngăn xếp cuộc gọi, Microtask và bộ hẹn giờ kèm ví dụ

Vòng lặp sự kiện JavaScript được giải thích bằng mã chúng tôi đã chạy: ngăn xếp cuộc gọi, hàng đợi tác vụ và vi nhiệm, tại sao setTimeout 0 không di…

Đọc bài viết →
Phát triển phần mềm

Giải thích về trình tạo và năng suất của Python: Tiết kiệm bộ nhớ bằng các ví dụ thực tế

Trình tạo và lợi nhuận Python được giải thích bằng mã chúng tôi đã chạy: cách chúng tạm dừng và tiếp tục, đo mức tiết kiệm bộ nhớ, quy trình, chuỗi …

Đọc bài viết →
Trí tuệ nhân tạo

Nhúng là gì? Giải thích sự tương đồng về vectơ và Cosine một cách đơn giản

nhúng là gì? Hướng dẫn bằng ngôn ngữ đơn giản về vectơ, độ tương tự cosine và tìm kiếm ngữ nghĩa, với một ví dụ nhỏ mà chúng tôi đã chạy, các cách s…

Đọc bài viết →
DevOps

Triển khai Blue-Green và Canary: Sự khác biệt, sự đánh đổi và cách lựa chọn

Giải thích về triển khai Blue-green và Canary: cách hoạt động của từng loại, chi phí, rủi ro và khôi phục, nhóm người dùng ổn định mà chúng tôi đã t…

Đọc bài viết →
Tự động hóa kiểm thử

Kiểm tra không ổn định: Nguyên nhân gây ra chúng và cách khắc phục chúng vĩnh viễn

Các thử nghiệm không ổn định được giải thích bằng các bản demo mà chúng tôi đã chạy: nguyên nhân chính, cách xác nhận và chẩn đoán nguyên nhân, cách…

Đọc bài viết →
Kiểm thử phần mềm

Kiểm tra tải và kiểm tra căng thẳng: Sự khác biệt, số liệu và ví dụ về k6

Giải thích về thử nghiệm tải và thử nghiệm căng thẳng: mỗi thử nghiệm chứng minh điều gì, thử nghiệm tăng đột biến và ngâm, số liệu quan trọng, lý d…

Đọc bài viết →
Kiểm thử phần mềm

Trường hợp thử nghiệm và kịch bản thử nghiệm: Sự khác biệt chính, ví dụ và thời điểm sử dụng từng trường hợp

Giải thích trường hợp kiểm thử và kịch bản kiểm thử: định nghĩa rõ ràng, bảng cạnh nhau, một tính năng đặt lại mật khẩu được lấy từ các tình huống n…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Tối ưu hóa truy vấn SQL: Đọc kế hoạch thực thi và sửa các truy vấn chậm, có tính thời gian

Đã thử nghiệm tối ưu hóa truy vấn SQL trên một triệu hàng: đọc kế hoạch thực hiện, thêm chỉ mục phù hợp, sửa các bộ lọc không thể mở rộng, sử dụng c…

Đọc bài viết →
Cơ sở dữ liệu & SQL

SQL UNION và UNION ALL: Sự khác biệt, ví dụ và hiệu suất đã được kiểm tra

SQL UNION và UNION ALL được giải thích bằng các truy vấn chúng tôi đã chạy: trùng lặp, cả hai quy tắc đều tuân theo, lỗi dữ liệu thực, hiệu suất đượ…

Đọc bài viết →
Phát triển phần mềm

Hướng dẫn API tìm nạp JavaScript: GET, POST, Xử lý lỗi và hết thời gian chờ

Hướng dẫn API tìm nạp JavaScript đã được thử nghiệm trên máy chủ cục bộ: GET và POST, tại sao 404 không gửi, trình trợ giúp có thể sử dụng lại, chuỗ…

Đọc bài viết →
Phát triển phần mềm

Xử lý tệp Python: Đọc, ghi, CSV, JSON và pathlib kèm ví dụ

Việc xử lý tệp Python được giải thích bằng mã chúng tôi đã chạy: chế độ mở, với, đọc tệp lớn, CSV, JSON, pathlib, tệp nhị phân, ghi an toàn, xử lý l…

Đọc bài viết →
Phát triển phần mềm

Các lớp và đối tượng Python: Hướng dẫn OOP với các ví dụ thực tế

Các lớp và đối tượng Python được giải thích bằng mã mà chúng tôi đã chạy: __init__, các phương thức, thuộc tính lớp và phiên bản, tính kế thừa, thuộ…

Đọc bài viết →
Trí tuệ nhân tạo

Mô hình ngôn ngữ lớn là gì? LLM hoạt động như thế nào, được giải thích mà không cường điệu hóa

Mô hình ngôn ngữ lớn là gì? LLM được giải thích bằng ngôn ngữ đơn giản: mã thông báo, phần nhúng, sự chú ý, đào tạo, cửa sổ nhiệt độ và ngữ cảnh, mộ…

Đọc bài viết →
DevOps

Các lệnh Linux cho người mới bắt đầu: Hướng dẫn thiết bị đầu cuối cần thiết kèm ví dụ

Các lệnh Linux dành cho người mới bắt đầu, được nhóm theo tác vụ: điều hướng, tệp, xem nhật ký, grep, đường dẫn, quyền, quy trình và lưu trữ, cùng v…

Đọc bài viết →
Tự động hóa kiểm thử

Selenium vs Nhà viết kịch: Sự khác biệt chính, So sánh mã và nên chọn cái nào

Selenium và Playwright được so sánh: kiến trúc, chờ đợi, hỗ trợ trình duyệt và ngôn ngữ, gỡ lỗi, kiểm tra giống nhau ở cả hai công cụ, lời khuyên di…

Đọc bài viết →
Kiểm thử phần mềm

Phân vùng tương đương: Giải thích kỹ thuật thiết kế thử nghiệm bằng các ví dụ đã thực hiện

Giải thích về phân vùng tương đương: cách tìm các phân vùng hợp lệ và không hợp lệ, các ví dụ hoạt động theo độ tuổi, mật khẩu và phiếu giảm giá, cá…

Đọc bài viết →
Kiểm thử phần mềm

Mức độ nghiêm trọng và mức độ ưu tiên trong kiểm thử phần mềm: Sự khác biệt, Ma trận và ví dụ thực tế

Giải thích về mức độ nghiêm trọng và mức độ ưu tiên trong kiểm thử phần mềm: định nghĩa rõ ràng, ma trận bốn chiều với các ví dụ, thang đo cấp độ, a…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Hướng dẫn về truy vấn con SQL: Các loại, truy vấn con tương quan và TỒN TẠI kèm ví dụ

Hướng dẫn về truy vấn con SQL với các truy vấn chúng tôi đã chạy: truy vấn con vô hướng, IN, FROM và SELECT, truy vấn con tương quan, EXISTS, bẫy và…

Đọc bài viết →
Cơ sở dữ liệu & SQL

Giải thích về giao dịch SQL và ACID: Các mức CAM KẾT, ROLLBACK và Cô lập

Các giao dịch SQL và ACID được giải thích bằng chuyển khoản ngân hàng mà chúng tôi đã thực hiện: CAM KẾT, ROLLBACK, điểm lưu trữ, khóa, mức cách ly,…

Đọc bài viết →
Phát triển phần mềm

Git merge vs rebase: khác biệt, ví dụ và khi nào dùng cái nào

Git merge vs rebase được giải thích bằng đầu ra log thực tế, bảng so sánh, quy tắc vàng của rebase và quy trình làm việc nhóm an toàn.

Đọc bài viết →
Phát triển phần mềm

List comprehension trong Python: cú pháp, ví dụ và khi nào nên tránh

List comprehension trong Python: cú pháp, lọc dữ liệu, if-else, vòng lặp lồng nhau, thời gian đo thực tế và khi nào vòng lặp for thông thường tốt hơn.

Đọc bài viết →
Cơ sở dữ liệu & SQL

Giải thích SQL JOIN kèm ví dụ (Inner, Left, Right, Full)

Hiểu SQL JOIN từng bước với bảng và truy vấn mẫu: INNER, LEFT, RIGHT, FULL, CROSS và SELF, cùng lỗi thường gặp và mẹo hiệu năng.

Đọc bài viết →