Để hiểu những gì đang xảy ra chắc chắn, tôi cần phải thực hiện một số sửa đổi cho kịch bản của bạn, nhưng ở đây có.
Đầu tiên, bạn có thể biết cách thức node
và event loop
hoạt động của nó , nhưng hãy để tôi tóm tắt nhanh. Khi bạn chạy một tập lệnh, node
trước tiên , thời gian chạy sẽ chạy phần đồng bộ của tập lệnh sau đó lên lịch promises
và timers
để được thực thi trên các vòng lặp tiếp theo và khi được kiểm tra chúng được giải quyết, hãy chạy các cuộc gọi lại trong một vòng lặp khác. Ý chính đơn giản này giải thích nó rất tốt, tín dụng cho @StephenGrider:
const pendingTimers = [];
const pendingOSTasks = [];
const pendingOperations = [];
// New timers, tasks, operations are recorded from myFile running
myFile.runContents();
function shouldContinue() {
// Check one: Any pending setTimeout, setInterval, setImmediate?
// Check two: Any pending OS tasks? (Like server listening to port)
// Check three: Any pending long running operations? (Like fs module)
return (
pendingTimers.length || pendingOSTasks.length || pendingOperations.length
);
}
// Entire body executes in one 'tick'
while (shouldContinue()) {
// 1) Node looks at pendingTimers and sees if any functions
// are ready to be called. setTimeout, setInterval
// 2) Node looks at pendingOSTasks and pendingOperations
// and calls relevant callbacks
// 3) Pause execution. Continue when...
// - a new pendingOSTask is done
// - a new pendingOperation is done
// - a timer is about to complete
// 4) Look at pendingTimers. Call any setImmediate
// 5) Handle any 'close' events
}
// exit back to terminal
Lưu ý rằng vòng lặp sự kiện sẽ không bao giờ kết thúc cho đến khi có các tác vụ HĐH đang chờ xử lý. Nói cách khác, việc thực thi nút của bạn sẽ không bao giờ kết thúc cho đến khi có các yêu cầu HTTP đang chờ xử lý.
Trong trường hợp của bạn, nó chạy một async
hàm, vì nó sẽ luôn trả lại một lời hứa, nó sẽ lên lịch để nó được thực hiện trong vòng lặp tiếp theo. Trên chức năng không đồng bộ của bạn, bạn lên lịch 1000 lời hứa (yêu cầu HTTP) cùng một lúc trong map
lần lặp đó . Sau đó, bạn đang chờ tất cả sau đó được giải quyết để kết thúc chương trình. Nó sẽ hoạt động, chắc chắn, trừ khi chức năng mũi tên ẩn danh của bạn map
không ném bất kỳ lỗi nào . Nếu một trong những lời hứa của bạn gây ra lỗi và bạn không xử lý nó, một số lời hứa sẽ không được gọi lại khiến chương trình kết thúc nhưng không thoát , vì vòng lặp sự kiện sẽ ngăn không cho đến khi thoát tất cả các nhiệm vụ, thậm chí không có cuộc gọi lại. Như nó nói trênPromise.all
docs : nó sẽ từ chối ngay khi lời hứa đầu tiên từ chối.
Vì vậy, ECONNRESET
lỗi của bạn không liên quan đến chính nút, là một cái gì đó với mạng của bạn đã khiến việc tìm nạp ném lỗi và sau đó ngăn vòng lặp sự kiện kết thúc. Với sửa chữa nhỏ này, bạn sẽ có thể thấy tất cả các yêu cầu được giải quyết không đồng bộ:
const fetch = require("node-fetch");
(async () => {
try {
const promises = Array(1000)
.fill(1)
.map(async (_value, index) => {
try {
const url = "https://google.com/";
const response = await fetch(url);
console.log(index, response.statusText);
return response;
} catch (e) {
console.error(index, e.message);
}
});
await Promise.all(promises);
} catch (e) {
console.error(e);
} finally {
console.log("Done");
}
})();
npx envinfo
, chạy ví dụ của bạn trên tập lệnh Win 10 / gậtv10.16.0 của tôi kết thúc sau 8432.805ms