Nodejs vòng lặp sự kiện là gì

Nút. js là thời gian chạy JavaScript hướng sự kiện không đồng bộ và hiệu quả nhất khi xây dựng các ứng dụng mạng có thể mở rộng. Nút. js không có khóa, vì vậy không có cơ hội khóa chết bất kỳ quy trình nào. vòng lặp sự kiện hoạt động và cách bạn có thể tận dụng nó để xây dựng các ứng dụng nhanh. Chúng tôi cũng sẽ thảo luận về những vấn đề phổ biến nhất mà bạn có thể gặp phải và giải pháp cho chúng

Với nút. js ở Quy mô, chúng tôi đang tạo một bộ sưu tập các bài viết tập trung vào nhu cầu của các công ty có Node lớn hơn. js và các nhà phát triển đã học những kiến ​​thức cơ bản về Node

Xem tất cả các chương của Node. js ở quy mô

  • Sử dụng npmnpm là sổ đăng ký phần mềm phục vụ hơn 1. 3 triệu gói. npm được sử dụng bởi các nhà phát triển nguồn mở từ khắp nơi trên thế giới để chia sẻ và mượn mã, cũng như nhiều doanh nghiệp. Có ba thành phần để npm. trang web Giao diện dòng lệnh (CLI) sổ đăng ký Sử dụng trang web để khám phá và tải xuống các gói, tạo hồ sơ người dùng và.
    • Thủ thuật npm và các phương pháp hay nhất
    • Xuất bản SemVer và Mô-đun
    • Hiểu Hệ thống Mô-đun, CommonJS và yêu cầu
  • Nút. js Internals Deep Dive
    • nút. js Vòng lặp sự kiện [ bài viết này ]
    • Nút. Giải thích về bộ sưu tập rác js
    • Viết nút gốc. mô-đun js
  • Xây dựng với nút. js
    • nút nâng cao. Cấu trúc dự án js
    • Các phương pháp hay nhất về mã hóa sạch JavaScript
    • Nút. js Thực tiễn tốt nhất về Async
    • Tìm nguồn cung ứng sự kiện với các ví dụ
    • Giải thích về CQRS (Phân tách trách nhiệm truy vấn lệnh)
  • Kiểm tra + Nút
    • Nút. js Kiểm tra và Bắt TDD đúng
    • Nút. js Thử nghiệm từ đầu đến cuối với Nightwatch. js
  • Nút. js trong sản xuất
    • Hướng dẫn dứt khoát để theo dõi nút. ứng dụng js
    • Cách gỡ lỗi nút. js với các công cụ tốt nhất hiện có
    • Nút. js Chẩn đoán & gỡ lỗi sau khi chết
  • Nút. js + MicroservicesMicroservices không phải là một công cụ, mà là một cách suy nghĩ khi xây dựng các ứng dụng phần mềm. Hãy bắt đầu giải thích với điều ngược lại. nếu bạn phát triển một ứng dụng độc lập, duy nhất và tiếp tục cải thiện toàn bộ ứng dụng đó, thì nó thường được gọi là ứng dụng nguyên khối. Theo thời gian, việc bảo trì và cập nhật nó ngày càng khó khăn hơn mà không vi phạm bất cứ điều gì, vì vậy chu kỳ phát triển có thể.
    • Truy tìm phân tán
    • Cổng API

Vấn đề

Hầu hết các chương trình phụ trợ đằng sau các trang web không cần thực hiện các phép tính phức tạp. Các chương trình của chúng tôi dành phần lớn thời gian để đợi đĩa đọc và ghi hoặc đợi dây truyền thông điệp của chúng tôi và gửi lại câu trả lời

Hoạt động IO có thể chậm hơn so với xử lý dữ liệu. Lấy cái này làm ví dụ. SSD-s có thể có tốc độ đọc 200-730 MB/s – ít nhất là loại cao cấp. Chỉ đọc một kilobyte dữ liệu sẽ mất 1. 4 micro giây, nhưng trong thời gian này, CPU có tốc độ 2GHz có thể đã thực hiện 28 000 chu kỳ xử lý lệnh

Đối với truyền thông mạng, nó có thể còn tồi tệ hơn, chỉ cần thử và ping google. com

$ ping google.com
64 bytes from 172.217.16.174: icmp_seq=0 ttl=52 time=33.017 ms
64 bytes from 172.217.16.174: icmp_seq=1 ttl=52 time=83.376 ms
64 bytes from 172.217.16.174: icmp_seq=2 ttl=52 time=26.552 ms
64 bytes from 172.217.16.174: icmp_seq=3 ttl=52 time=40.153 ms
64 bytes from 172.217.16.174: icmp_seq=4 ttl=52 time=37.291 ms
64 bytes from 172.217.16.174: icmp_seq=5 ttl=52 time=58.692 ms
64 bytes from 172.217.16.174: icmp_seq=6 ttl=52 time=45.245 ms
64 bytes from 172.217.16.174: icmp_seq=7 ttl=52 time=27.846 ms

Độ trễ trung bình là khoảng 44 mili giây. Chỉ trong khi đợi một gói thực hiện một chuyến khứ hồi trên dây, bộ xử lý đã đề cập trước đó có thể thực hiện 88 triệu chu kỳ

Giải pháp

Hầu hết các hệ điều hành đều cung cấp một số loại giao diện IO không đồng bộ, cho phép bạn bắt đầu xử lý dữ liệu không yêu cầu kết quả của giao tiếp, trong khi giao tiếp vẫn tiếp tục

Điều này có thể đạt được bằng nhiều cách. Ngày nay, nó chủ yếu được thực hiện bằng cách tận dụng khả năng đa luồng với chi phí phức tạp hơn của phần mềm. Ví dụ: đọc một tệp bằng Java hoặc Python là một thao tác chặn. Chương trình của bạn không thể làm bất cứ điều gì khác trong khi chờ giao tiếp mạng/đĩa kết thúc. Tất cả những gì bạn có thể làm - ít nhất là trong Java - là kích hoạt một luồng khác rồi thông báo cho luồng chính của bạn khi thao tác kết thúc

Nó tẻ nhạt, phức tạp, nhưng hoàn thành công việc. Nhưng còn Node thì sao? . js – hoặc giống như V8 – là đơn luồng. Mã của chúng tôi chỉ có thể chạy trong một chuỗi

CHỈNH SỬA. Điều này không hoàn toàn đúng. Cả Java và Python đều có không đồng bộKhông đồng bộ, trong lập trình phần mềm, đề cập đến các sự kiện xảy ra bên ngoài luồng chương trình chính và các phương pháp xử lý chúng. Các sự kiện bên ngoài chẳng hạn như tín hiệu hoặc hoạt động được nhắc bởi một chương trình xảy ra cùng lúc với việc thực hiện chương trình mà không khiến chương trình bị chặn và chờ kết quả là những ví dụ về thể loại này. Đầu vào/đầu ra không đồng bộ là một. giao diện, nhưng sử dụng chúng chắc chắn khó hơn trong Node. js. Cảm ơn Shahar và Dirk Harrington đã chỉ ra điều này.

Bạn có thể đã nghe nói rằng trong trình duyệt, cài đặt setTimeout(someFunction, 0) đôi khi có thể khắc phục mọi thứ một cách kỳ diệu. Nhưng tại sao việc đặt thời gian chờ thành 0, trì hoãn thực thi trong 0 mili giây lại khắc phục được điều gì?

Trước hết, chúng ta hãy xem ngăn xếp cuộc gọi, hay đơn giản là “ngăn xếp”. Tôi sẽ làm cho mọi thứ trở nên đơn giản, vì chúng ta chỉ cần hiểu những điều cơ bản của ngăn xếp cuộc gọi. Trong trường hợp bạn đã quen với cách thức hoạt động của nó, vui lòng chuyển sang phần tiếp theo

Cây rơm

Bất cứ khi nào bạn gọi địa chỉ trả về của hàm, các tham số và biến cục bộ sẽ được đẩy vào ngăn xếp. Nếu bạn gọi một chức năng khác từ chức năng hiện đang chạy, nội dung của nó sẽ được đẩy lên trên cùng theo cách giống như chức năng trước đó – với địa chỉ trả về của nó

Để đơn giản, tôi sẽ nói rằng 'một chức năng được đẩy' lên đầu ngăn xếp kể từ bây giờ, mặc dù nó không hoàn toàn chính xác

Hãy cùng xem

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()

main được gọi đầu tiên

Nodejs vòng lặp sự kiện là gì

sau đó gọi chính getLengthOfHypotenuse với 3 và 4 làm đối số

Nodejs vòng lặp sự kiện là gì

sau đó hình vuông có giá trị là 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
0

Nodejs vòng lặp sự kiện là gì

khi hình vuông trả về, nó được bật ra khỏi ngăn xếp và giá trị trả về của nó được chỉ định cho 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
1. squareA được thêm vào khung ngăn xếp của 
 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
2

Nodejs vòng lặp sự kiện là gì

tương tự cho cuộc gọi tiếp theo tới hình vuông

Nodejs vòng lặp sự kiện là gì
Nodejs vòng lặp sự kiện là gì

ở dòng tiếp theo, biểu thức 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
3 được đánh giá

Nodejs vòng lặp sự kiện là gì

rồi Toán. sqrt được gọi với sumOfSquares

Nodejs vòng lặp sự kiện là gì

bây giờ tất cả những gì còn lại dành cho 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
2 là trả về giá trị cuối cùng của phép tính

Nodejs vòng lặp sự kiện là gì

giá trị trả về được chỉ định cho 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
5 trong main

Nodejs vòng lặp sự kiện là gì

giá trị của 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
5 được ghi vào bảng điều khiển

Nodejs vòng lặp sự kiện là gì

cuối cùng, main trả về mà không có bất kỳ giá trị nào, được lấy ra khỏi ngăn xếp để trống

Nodejs vòng lặp sự kiện là gì

LƯU Ý BÊN LỀ. Bạn đã thấy rằng các biến cục bộ được bật ra khỏi ngăn xếp khi quá trình thực thi hàm kết thúc. Nó chỉ xảy ra khi bạn làm việc với các giá trị đơn giản như số, chuỗi và booleans. Giá trị của các đối tượng, mảng và như vậy được lưu trữ trong heap và biến của bạn chỉ là một con trỏ tới chúng. Nếu bạn chuyển biến này, bạn sẽ chỉ chuyển con trỏ đã nói, làm cho các giá trị này có thể thay đổi trong các khung ngăn xếp khác nhau. Khi chức năng được bật ra khỏi ngăn xếp, chỉ con trỏ tới Đối tượng được bật lên khi để lại giá trị thực trong đống. Người thu gom rác là người đảm nhiệm việc giải phóng không gian sau khi các đồ vật hết hạn sử dụng

Nhập nút. vòng lặp sự kiện js

Nodejs vòng lặp sự kiện là gì

Không, không phải vòng lặp này. 🙂

Vậy điều gì sẽ xảy ra khi chúng ta gọi thứ gì đó như 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
9, 
'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
0, 
'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
1 hoặc 
'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
2? . js. Để hiểu điều này, chúng ta sẽ phải hiểu thứ tự thực hiện tốt hơn một chút

Chúng ta hãy xem một Node phổ biến hơn. ứng dụng js – một máy chủ đang lắng nghe trên 

'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
3. Khi nhận được yêu cầu, máy chủ sẽ gọi số 
'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
4 để biết thông tin thời tiết, in một số thông báo loại tới bảng điều khiển và máy chủ sẽ chuyển tiếp phản hồi cho người gọi sau khi nhận được chúng

'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)

Điều gì sẽ được in ra ngoài việc xem thông tin thời tiết khi yêu cầu được gửi tới

'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
5?

Nếu bạn có một số kinh nghiệm với Node, bạn không nên ngạc nhiên rằng mặc dù 

'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
6 được gọi sau 
'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
7 trong mã, nhưng phần trước sẽ được in trước dẫn đến kết quả

Fetching the weather, please be patient
Hi
Got the weather

Chuyện gì đã xảy ra thế? . Điều đó có nghĩa là bất cứ khi nào chúng ta gọi thứ gì đó là non-blocking operation, Node sẽ gọi một số mã sẽ chạy đồng thời với mã javascript của chúng ta. Khi chuỗi ẩn này nhận được giá trị mà nó đang chờ hoặc đưa ra lỗi, cuộc gọi lại được cung cấp sẽ được gọi với các tham số cần thiết

LƯU Ý BÊN LỀ. 'Một số mã' mà chúng tôi đã đề cập thực sự là một phần của libuv. libuv là thư viện nguồn mở xử lý nhóm luồng, thực hiện tín hiệu và tất cả các phép thuật khác cần thiết để làm cho các tác vụ không đồng bộ hoạt động. Ban đầu nó được phát triển cho Node. js nhưng rất nhiều dự án khác hiện đang sử dụng nó

Cần trợ giúp với Node cấp doanh nghiệp. Phát triển js?

Thuê nút. js chuyên gia của RisingStack

Để tìm hiểu sâu hơn, chúng tôi cần giới thiệu hai khái niệm mới. vòng lặp sự kiện và hàng đợi nhiệm vụ

hàng đợi nhiệm vụ

Javascript là ngôn ngữ đơn luồng, hướng sự kiện. Điều này có nghĩa là chúng tôi có thể đính kèm người nghe vào các sự kiện và khi một sự kiện đã nói kích hoạt, người nghe sẽ thực hiện cuộc gọi lại mà chúng tôi đã cung cấp

Bất cứ khi nào bạn gọi 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
9, 
'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
0 hoặc 
'use strict'
const express = require('express')
const superagent = require('superagent')
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {
  console.log('Hi')
}

app.listen(3000)
2, Node. js gửi các thao tác này đến một luồng khác cho phép V8 tiếp tục thực thi mã của chúng tôi. Nút cũng gọi cuộc gọi lại khi bộ đếm ngừng hoạt động hoặc thao tác IO/http kết thúc

Các cuộc gọi lại này có thể xử lý các tác vụ khác và các hàm đó có thể xử lý các tác vụ khác, v.v. Bằng cách này, bạn có thể đọc tệp trong khi xử lý yêu cầu trong máy chủ của mình, sau đó thực hiện cuộc gọi http dựa trên nội dung đã đọc mà không chặn xử lý các yêu cầu khác

Tuy nhiên, chúng tôi chỉ có một luồng chính và một ngăn xếp cuộc gọi, vì vậy trong trường hợp có một yêu cầu khác được phục vụ khi tệp đã nói được đọc, cuộc gọi lại của nó sẽ cần đợi ngăn xếp trở nên trống rỗng. Tình trạng lấp lửng nơi các cuộc gọi lại đang chờ đến lượt chúng được thực thi được gọi là hàng đợi nhiệm vụ (hoặc hàng đợi sự kiện hoặc hàng đợi tin nhắn). Các cuộc gọi lại đang được gọi trong một vòng lặp vô hạn bất cứ khi nào luồng chính hoàn thành nhiệm vụ trước đó, do đó có tên là 'vòng lặp sự kiện'

Trong ví dụ trước của chúng tôi, nó sẽ giống như thế này

  1. express đăng ký một trình xử lý cho sự kiện 'yêu cầu' sẽ được gọi khi yêu cầu đến '/'
  2. bỏ qua các chức năng và bắt đầu nghe trên cổng 3000
  3. ngăn xếp trống, đang chờ sự kiện 'yêu cầu' kích hoạt
  4. khi có yêu cầu đến, sự kiện được chờ đợi từ lâu sẽ kích hoạt, gọi cấp tốc cho trình xử lý được cung cấp
    Fetching the weather, please be patient
    Hi
    Got the weather
    
    1
  5. Fetching the weather, please be patient
    Hi
    Got the weather
    
    1 được đẩy vào ngăn xếp
  6. Fetching the weather, please be patient
    Hi
    Got the weather
    
    3 được gọi và đẩy vào ngăn xếp
  7. Fetching the weather, please be patient
    Hi
    Got the weather
    
    4 và 
    Fetching the weather, please be patient
    Hi
    Got the weather
    
    5 được gọi, đẩy vào ngăn xếp và bật ra, a từ 
    Fetching the weather, please be patient
    Hi
    Got the weather
    
    6 được chỉ định cho 
    Fetching the weather, please be patient
    Hi
    Got the weather
    
    7
  8. Fetching the weather, please be patient
    Hi
    Got the weather
    
    8 được gọi với 
    Fetching the weather, please be patient
    Hi
    Got the weather
    
    9, trình xử lý được đặt cho sự kiện 
    console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    0
  9. yêu cầu http tới 
    console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    1 được gửi tới chuỗi nền và quá trình thực thi tiếp tục
  10. console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    2 được ghi vào bảng điều khiển, 
    Fetching the weather, please be patient
    Hi
    Got the weather
    
    3 trả về
  11. console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    4 được gọi, 
    console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    5 được in ra bảng điều khiển
  12. Fetching the weather, please be patient
    Hi
    Got the weather
    
    1 trả về, được lấy ra khỏi ngăn xếp để trống
  13. đang đợi 
    console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    1 gửi phản hồi
  14. sau khi có phản hồi, sự kiện 
    console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    0 được kích hoạt
  15. console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    9 chúng tôi đã chuyển đến 
    script start
    promise1
    promise2
    setInterval
    setTimeout1
    promise3
    promise4
    setInterval
    setTimeout2
    setInterval
    promise5
    promise6
    
    0 được gọi, được đẩy vào ngăn xếp với tất cả các biến trong phần đóng của nó, nghĩa là nó có thể nhìn thấy và sửa đổi các giá trị của 
    script start
    promise1
    promise2
    setInterval
    setTimeout1
    promise3
    promise4
    setInterval
    setTimeout2
    setInterval
    promise5
    promise6
    
    1 và tất cả các hàm chúng tôi đã xác định
  16. script start
    promise1
    promise2
    setInterval
    setTimeout1
    promise3
    promise4
    setInterval
    setTimeout2
    setInterval
    promise5
    promise6
    
    2 được gọi với 
    script start
    promise1
    promise2
    setInterval
    setTimeout1
    promise3
    promise4
    setInterval
    setTimeout2
    setInterval
    promise5
    promise6
    
    3 hoặc 
    script start
    promise1
    promise2
    setInterval
    setTimeout1
    promise3
    promise4
    setInterval
    setTimeout2
    setInterval
    promise5
    promise6
    
    4 mã trạng thái, nhưng mã này lại được gửi tới chuỗi nền, do đó, luồng phản hồi không chặn quá trình thực thi của chúng tôi, 
    console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      Promise.resolve().then(() => {
        console.log('promise 3')
      }).then(() => {
        console.log('promise 4')
      }).then(() => {
        setTimeout(() => {
          console.log('setTimeout 2')
          Promise.resolve().then(() => {
            console.log('promise 5')
          }).then(() => {
            console.log('promise 6')
          }).then(() => {
            clearInterval(interval)
          })
        }, 0)
      })
    }, 0)
    
    Promise.resolve().then(() => {
      console.log('promise 1')
    }).then(() => {
      console.log('promise 2')
    })
    
    9 được lấy ra khỏi ngăn xếp

Vì vậy, bây giờ chúng ta có thể hiểu tại sao bản hack 

 1 function main () {
 2   const hypotenuse = getLengthOfHypotenuse(3, 4)
 3   console.log(hypotenuse)
 4 }
 5
 6 function getLengthOfHypotenuse(a, b) {
 7   const squareA = square(a)
 8   const squareB = square(b)
 9   const sumOfSquares = squareA + squareB
10   return Math.sqrt(sumOfSquares)
11 }
12
13 function square(number) {
14   return number * number
15 }
16 
17 main()
9 được đề cập trước đó lại hoạt động. Mặc dù chúng tôi đặt bộ đếm thành 0, nhưng nó sẽ trì hoãn việc thực thi cho đến khi ngăn xếp hiện tại và hàng đợi tác vụ trống, cho phép trình duyệt vẽ lại giao diện người dùng hoặc Nút để phục vụ các yêu cầu khác

Nhiệm vụ vi mô và nhiệm vụ vĩ mô

Nếu điều này là không đủ, chúng tôi thực sự có nhiều hơn một hàng đợi nhiệm vụ. Một cho các tác vụ vi mô và một cho các tác vụ vĩ mô

ví dụ về microtask

  • 'use strict'
    const express = require('express')
    const superagent = require('superagent')
    const app = express()
    
    app.get('/', sendWeatherOfRandomCity)
    
    function sendWeatherOfRandomCity (request, response) {
      getWeatherOfRandomCity(request, response)
      sayHi()
    }
    
    const CITIES = [
      'london',
      'newyork',
      'paris',
      'budapest',
      'warsaw',
      'rome',
      'madrid',
      'moscow',
      'beijing',
      'capetown',
    ]
    
    function getWeatherOfRandomCity (request, response) {
      const city = CITIES[Math.floor(Math.random() * CITIES.length)]
      superagent.get(`wttr.in/${city}`)
        .end((err, res) => {
          if (err) {
            console.log('O snap')
            return response.status(500).send('There was an error getting the weather, try looking out the window')
          }
          const responseText = res.text
          response.send(responseText)
          console.log('Got the weather')
        })
    
      console.log('Fetching the weather, please be patient')
    }
    
    function sayHi () {
      console.log('Hi')
    }
    
    app.listen(3000)
    
    1
  • script start
    promise1
    promise2
    setInterval
    setTimeout1
    promise3
    promise4
    setInterval
    setTimeout2
    setInterval
    promise5
    promise6
    
    8
  • script start
    promise1
    promise2
    setInterval
    setTimeout1
    promise3
    promise4
    setInterval
    setTimeout2
    setInterval
    promise5
    promise6
    
    9

ví dụ về macrotask

  •  1 function main () {
     2   const hypotenuse = getLengthOfHypotenuse(3, 4)
     3   console.log(hypotenuse)
     4 }
     5
     6 function getLengthOfHypotenuse(a, b) {
     7   const squareA = square(a)
     8   const squareB = square(b)
     9   const sumOfSquares = squareA + squareB
    10   return Math.sqrt(sumOfSquares)
    11 }
    12
    13 function square(number) {
    14   return number * number
    15 }
    16 
    17 main()
    
    9
  • console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      process.nextTick(() => {
        console.log('nextTick 3')
        process.nextTick(() => {
          console.log('nextTick 4')
          setTimeout(() => {
            console.log('setTimeout 2')
            process.nextTick(() => {
              console.log('nextTick 5')
              process.nextTick(() => {
                console.log('nextTick 6')
                clearInterval(interval)
              })
            })
          }, 0)
        })
      })
    })
    
    process.nextTick(() => {
      console.log('nextTick 1')
      process.nextTick(() => {
        console.log('nextTick 2')
      })
    })
    
    1
  • console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      process.nextTick(() => {
        console.log('nextTick 3')
        process.nextTick(() => {
          console.log('nextTick 4')
          setTimeout(() => {
            console.log('setTimeout 2')
            process.nextTick(() => {
              console.log('nextTick 5')
              process.nextTick(() => {
                console.log('nextTick 6')
                clearInterval(interval)
              })
            })
          }, 0)
        })
      })
    })
    
    process.nextTick(() => {
      console.log('nextTick 1')
      process.nextTick(() => {
        console.log('nextTick 2')
      })
    })
    
    2
  • console.log('script start')
    
    const interval = setInterval(() => {
      console.log('setInterval')
    }, 0)
    
    setTimeout(() => {
      console.log('setTimeout 1')
      process.nextTick(() => {
        console.log('nextTick 3')
        process.nextTick(() => {
          console.log('nextTick 4')
          setTimeout(() => {
            console.log('setTimeout 2')
            process.nextTick(() => {
              console.log('nextTick 5')
              process.nextTick(() => {
                console.log('nextTick 6')
                clearInterval(interval)
              })
            })
          }, 0)
        })
      })
    })
    
    process.nextTick(() => {
      console.log('nextTick 1')
      process.nextTick(() => {
        console.log('nextTick 2')
      })
    })
    
    3

Hãy xem đoạn mã sau

console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  Promise.resolve().then(() => {
    console.log('promise 3')
  }).then(() => {
    console.log('promise 4')
  }).then(() => {
    setTimeout(() => {
      console.log('setTimeout 2')
      Promise.resolve().then(() => {
        console.log('promise 5')
      }).then(() => {
        console.log('promise 6')
      }).then(() => {
        clearInterval(interval)
      })
    }, 0)
  })
}, 0)

Promise.resolve().then(() => {
  console.log('promise 1')
}).then(() => {
  console.log('promise 2')
})

điều này sẽ đăng nhập vào bảng điều khiển

script start
promise1
promise2
setInterval
setTimeout1
promise3
promise4
setInterval
setTimeout2
setInterval
promise5
promise6

Theo thông số kỹ thuật, chính xác một tác vụ (macro) sẽ được xử lý từ hàng đợi tác vụ macro trong một chu kỳ của vòng lặp sự kiện. Sau khi macrotask đã nói kết thúc, tất cả các microtask có sẵn sẽ được xử lý trong cùng một chu kỳ. Trong khi các vi nhiệm vụ này đang được xử lý, chúng có thể xếp hàng nhiều vi nhiệm vụ hơn, tất cả các vi nhiệm vụ này sẽ được chạy từng cái một cho đến khi hết hàng đợi vi nhiệm vụ

Sơ đồ này cố gắng làm cho hình ảnh rõ ràng hơn một chút

Nodejs vòng lặp sự kiện là gì

Trong trường hợp của chúng ta

chu kỳ 1

  1. `setInterval` được lên lịch làm nhiệm vụ
  2. `setTimeout 1` được lên lịch làm tác vụ
  3. trong `Lời hứa. giải quyết 1` cả `then` được lên lịch dưới dạng vi tác vụ
  4. ngăn xếp trống, vi tác vụ được chạy

hàng đợi nhiệm vụ.

console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})
1, 
console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})
5

chu kỳ 2

  1. hàng đợi vi tác vụ trống, trình xử lý của `setInteval` có thể chạy, một `setInterval` khác được lên lịch làm tác vụ, ngay sau `setTimeout 1`

hàng đợi nhiệm vụ.

console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})
5, 
console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})
1

Chu kỳ 3

  1. hàng đợi vi tác vụ trống, trình xử lý `setTimeout 1` có thể chạy, `promise 3` và `promise 4` được lên lịch làm vi tác vụ,
  2. trình xử lý của `promise 3` và `promise 4` đang chạy `setTimeout 2` được lên lịch làm tác vụ

hàng đợi nhiệm vụ.

console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})
1, 
console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})
9

Chu kỳ 4

  1. hàng đợi vi tác vụ trống, trình xử lý của `setInteval` có thể chạy, một `setInterval` khác được lên lịch làm tác vụ, ngay sau `setTimeout`

hàng đợi nhiệm vụ.

console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})
9, setTimeout(someFunction, 0)1

  1. Trình xử lý của `setTimeout 2` chạy, `promise 5` và `promise 6` được lên lịch dưới dạng vi nhiệm vụ

Bây giờ, trình xử lý của setTimeout(someFunction, 0)2 và setTimeout(someFunction, 0)3 sẽ được chạy sau khoảng thời gian của chúng ta, nhưng vì một lý do kỳ lạ nào đó, _______53_______1 lại được chạy lại. Tuy nhiên, nếu bạn chạy mã này trong Chrome, bạn sẽ nhận được hành vi dự kiến

Chúng tôi cũng có thể sửa lỗi này trong Node bằng quy trình. nextTick và một số địa ngục gọi lại khó hiểu

console.log('script start')

const interval = setInterval(() => {
  console.log('setInterval')
}, 0)

setTimeout(() => {
  console.log('setTimeout 1')
  process.nextTick(() => {
    console.log('nextTick 3')
    process.nextTick(() => {
      console.log('nextTick 4')
      setTimeout(() => {
        console.log('setTimeout 2')
        process.nextTick(() => {
          console.log('nextTick 5')
          process.nextTick(() => {
            console.log('nextTick 6')
            clearInterval(interval)
          })
        })
      }, 0)
    })
  })
})

process.nextTick(() => {
  console.log('nextTick 1')
  process.nextTick(() => {
    console.log('nextTick 2')
  })
})

Đây là logic chính xác giống như những lời hứa yêu dấu của chúng tôi sử dụng, chỉ là một chút gớm ghiếc hơn. Ít nhất thì nó cũng hoàn thành công việc theo cách chúng ta mong đợi

Chế ngự con thú không đồng bộ

Như chúng ta đã thấy, chúng ta cần quản lý và chú ý đến cả hàng đợi tác vụ và vòng lặp sự kiện khi chúng ta viết một ứng dụng trong Node. js - trong trường hợp chúng tôi muốn tận dụng tất cả sức mạnh của nó và nếu chúng tôi muốn giữ cho các tác vụ chạy dài của mình không chặn luồng chính

Ban đầu, vòng lặp sự kiện có thể là một khái niệm khó nắm bắt, nhưng một khi bạn đã hiểu rõ về nó, bạn sẽ không thể tưởng tượng rằng có sự sống nếu không có nó. Kiểu truyền liên tục có thể dẫn đến địa ngục gọi lại có thể trông xấu xí, nhưng chúng tôi có Lời hứa và chúng tôi sẽ sớm có async-await trong tay… và trong khi chúng tôi đang (a)chờ đợi, bạn có thể mô phỏng async-await bằng cách sử dụng co và

Một lời khuyên chia tay cuối cùng

Biết cách Node. js và V8 xử lý các lệnh thực thi trong thời gian dài, bạn có thể bắt đầu sử dụng nó vì lợi ích của riêng mình. Trước đây bạn có thể đã nghe nói rằng bạn nên gửi các vòng lặp đang chạy dài của mình vào hàng đợi tác vụ. Bạn có thể làm thủ công hoặc sử dụng async. js

Mã hóa vui vẻ

Nếu bạn có bất kỳ câu hỏi hoặc suy nghĩ nào, hãy chia sẻ chúng trong phần bình luận, tôi sẽ ở đó. Phần tiếp theo của Nút. js tại Chuỗi quy mô đang thảo luận về Bộ sưu tập rác trong Node. js, tôi khuyên bạn nên kiểm tra nó

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

JavaScript có mô hình thời gian chạy dựa trên vòng lặp sự kiện, chịu trách nhiệm thực thi mã, thu thập và xử lý sự kiện cũng như thực hiện các tác vụ phụ được xếp hàng đợi. This model is quite different from models in other languages like C and Java.

Vòng lặp sự kiện và Eventemitter trong nút JS là gì?

Vòng lặp sự kiện trong Nodejs. Để đạt được nó, nodejs có các sự kiện và cuộc gọi lại. Vòng lặp sự kiện là một vòng lặp vô hạn và trong mỗi lần lặp, nó sẽ kiểm tra hàng đợi sự kiện xem có sự kiện nào được kích hoạt không, nếu tìm thấy thì thực hiện và xóa nó khỏi hàng đợi

Tại sao vòng lặp sự kiện cần thiết?

Vòng lặp sự kiện hỗ trợ quá trình này; . Nếu nó trống, các chức năng mới sẽ được thêm vào từ hàng đợi sự kiện. Nếu không, thì lệnh gọi hàm hiện tại được xử lý. it constantly checks whether or not the call stack is empty. If it is empty, new functions are added from the event queue. If it is not, then the current function call is processed.

Sự khác biệt giữa gọi lại và vòng lặp sự kiện là gì?

Hàng gọi lại. Sau khi bộ hẹn giờ hết hạn, chức năng gọi lại được đặt bên trong Hàng đợi gọi lại và Vòng lặp sự kiện sẽ kiểm tra xem Ngăn xếp cuộc gọi có trống không và nếu trống, sẽ đẩy chức năng gọi lại từ Hàng đợi gọi lại vào Ngăn xếp cuộc gọi . .