Memahami Pengaturcaraan Asynchronous dalam JavaScript: Panduan Pemula untuk Gelung Acara

PHPz
Lepaskan: 2024-09-11 06:32:03
asal
801 orang telah melayarinya

Understanding Asynchronous Programming in JavaScript: Beginner

Pernahkah anda terfikir mengapa beberapa keping kod JavaScript kelihatan kehabisan pesanan? Kunci untuk memahami perkara ini ialah gelung acara.

Gelung acara JavaScript boleh menjadi sukar untuk difahami, terutamanya apabila berurusan dengan pelbagai jenis operasi tak segerak. Dalam artikel ini, kami akan membahagikan cara JavaScript mengendalikan kod segerak dan tak segerak, tugas mikro dan tugasan makro serta sebab perkara tertentu berlaku dalam susunan tertentu.

Jadual Kandungan

  1. Kod Segerak dan Tak Segerak
    • Apakah itu Kod Segerak
    • Apakah itu Kod Asynchronous
    • Corak Asynchronous dalam JavaScript
    • Kod Segerak lwn Tak Segerak
  2. Tugasan mikro dan tugasan makro
    • Apakah itu Microtasks
    • Apakah itu Tugasan Makro
    • Microtasks vs Macrotasks
  3. Gelung Peristiwa
    • Apakah Gelung Acara
    • Cara Gelung Acara Berfungsi
  4. Contoh
    • Contoh 1: Pemasa dengan Janji dan Gelung Acara
    • Contoh 2: Janji Bersarang dan Pemasa
    • Contoh 3: Campuran Operasi Segerak dan Tak Segerak
  5. Kesimpulan

Kod Segerak dan Tak Segerak

JavaScript mengendalikan operasi dalam dua cara utama: synchronous dan asynchronous. Memahami perbezaan antara mereka adalah kunci untuk memahami cara JavaScript mengendalikan tugas dan cara menulis kod yang cekap dan tidak menyekat.

Apakah Kod Segerak?

Kod segerak ialah lalai dalam JavaScript, bermakna setiap baris berjalan satu demi satu dalam urutan. Contohnya:

console.log("First");
console.log("Second");
Salin selepas log masuk

Ini akan menghasilkan:

First
Second
Salin selepas log masuk

Apakah Kod Asynchronous?

Kod tak segerak sebaliknya membenarkan tugasan tertentu dijalankan di latar belakang dan diselesaikan kemudian, tanpa menyekat kod yang lain. Fungsi seperti setTimeout() atau Promise ialah contoh kod tak segerak.

Berikut ialah contoh mudah kod tak segerak menggunakan setTimeout():

console.log("First");

setTimeout(() => {
  console.log("Second");
}, 0);

console.log("Third");
Salin selepas log masuk

Ini akan menghasilkan:

First
Third
Second
Salin selepas log masuk

Corak Asynchronous dalam JavaScript:

Terdapat beberapa cara untuk mengendalikan operasi tak segerak dalam JavaScript:

  1. Panggil balik: Fungsi yang dihantar sebagai argumen kepada fungsi lain dan dilaksanakan selepas fungsi pertama menyelesaikan tugasnya.

Contoh Kod:

console.log("Start");

function asyncTask(callback) {
  setTimeout(() => {
    console.log("Async task completed");
    callback();
  }, 2000);
}

asyncTask(() => {
  console.log("Task finished");
});

console.log("End");
Salin selepas log masuk
  1. Janji: Janji mewakili nilai (atau ralat) masa hadapan yang akhirnya akan dikembalikan oleh fungsi tak segerak.

Contoh Kod:

console.log("Start");

const asyncTask = new Promise((resolve) => {
  setTimeout(() => {
    console.log("Async task completed");
    resolve();
  }, 2000);
});

asyncTask.then(() => {
  console.log("Task finished");
});

console.log("End");
Salin selepas log masuk
  1. Async/Await: Async/wait ialah gula sintaktik yang dibina di atas janji, membolehkan kami menulis kod tak segerak yang kelihatan segerak.

Contoh Kod:

console.log("Start");

async function asyncTask() {
  await new Promise((resolve) => {
    setTimeout(() => {
      console.log("Async task completed");
      resolve();
    }, 2000);
  });

  console.log("Task finished");
}

asyncTask();

console.log("End");
Salin selepas log masuk

Kod Segerak vs Asynchronous

Untuk lebih memahami setiap kaedah pelaksanaan javascript ini dan bagaimana ia berbeza daripada setiap satu sama ada, berikut ialah perbezaan terperinci merentas pelbagai aspek fungsi javascript.

Aspect Synchronous Code Asynchronous Code
Execution Order Executes line by line in a sequential manner Allows tasks to run in the background while other code continues to execute
Performance Can lead to performance issues if long-running tasks are involved Better performance for I/O-bound operations; prevents UI freezing in browser environments
Code Complexity Generally simpler and easier to read Can be more complex, especially with nested callbacks (callback hell)
Memory Usage May use more memory if waiting for long operations Generally more memory-efficient for long-running tasks
Scalability Less scalable for applications with many concurrent operations More scalable, especially for applications handling multiple simultaneous operations

This comparison highlights the key differences between synchronous and asynchronous code, helping developers choose the appropriate approach based on their specific use case and performance requirements.


Microtasks and Macrotasks

In JavaScript, microtasks and macrotasks are two types of tasks that are queued and executed in different parts of the event loop, which determines how JavaScript handles asynchronous operations.

Microtasks and macrotasks are both queued and executed in the event loop, but they have different priorities and execution contexts. Microtasks are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue. Macrotasks, on the other hand, are executed after the microtask queue has been emptied and before the next event loop cycle starts.

What are Microtasks

Microtasks are tasks that need to be executed after the current operation completes but before the next event loop cycle starts. Microtasks get priority over macrotasks and are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue.

Examples of microtasks:

  • Promises (when using .then() or .catch() handlers)
  • MutationObserver callbacks (used to observe changes to the DOM)
  • Some process.nextTick() in Node.js

Code Sample

console.log("Start");

Promise.resolve().then(() => {
  console.log("Microtask");
});

console.log("End");
Salin selepas log masuk

Output:

Start
End
Microtask
Salin selepas log masuk

Explanation:

  • The code first logs "Start", which is synchronous.
  • The promise handler (Microtask) is queued as microtask.
  • The "End" is logged (synchronous), then the event loop processes the microtask, logging "Microtask".

What are Macrotasks

Macrotasks are tasks that are executed after the microtask queue has been emptied and before the next event loop cycle starts. These tasks represent operations like I/O or rendering and are usually scheduled after a certain event or after a delay.

Examples of macrotasks:

  • setTimeout()
  • setInterval()
  • setImmediate() (in Node.js)
  • I/O callbacks (file reading/writing)
  • UI rendering tasks (in browsers)

Code Example:

console.log("Start");

setTimeout(() => {
  console.log("Macrotask");
}, 0);

console.log("End");
Salin selepas log masuk

Output:

Start
End
Macrotask
Salin selepas log masuk

Explanation:

  • The code first logs "Start", which is synchronous.
  • The setTimeout() (macrotask) is queued.
  • The "End" is logged (synchronous), then the event loop processes the macrotask, logging "Macrotask".

Microtasks vs Macrotasks

Aspect Microtasks Macrotasks
Execution Timing Executed immediately after the current script, before rendering Executed in the next event loop iteration
Queue Priority Higher priority, processed before macrotasks Lower priority, processed after all microtasks are complete
Examples Promises, queueMicrotask(), MutationObserver setTimeout(), setInterval(), I/O operations, UI rendering
Use Case For tasks that need to be executed as soon as possible without yielding to the event loop For tasks that can be deferred or don't require immediate execution

Gelung Peristiwa

Gelung peristiwa ialah konsep asas dalam JavaScript yang membolehkan operasi tak segerak tanpa sekatan walaupun JavaScript berbenang tunggal. Ia bertanggungjawab untuk mengendalikan panggilan balik tak segerak dan memastikan JavaScript terus berjalan lancar tanpa disekat oleh operasi yang memakan masa.

Apakah Gelung Acara

Gelung acara ialah mekanisme yang membenarkan JavaScript mengendalikan operasi tak segerak dengan cekap. Ia sentiasa menyemak timbunan panggilan dan baris gilir tugas (atau baris gilir microtask) untuk menentukan fungsi mana yang perlu dilaksanakan seterusnya.

Untuk memahami gelung acara dengan lebih baik, adalah penting untuk mengetahui cara JavaScript berfungsi secara dalaman. Adalah penting untuk ambil perhatian bahawa JavaScript ialah bahasa benang tunggal, bermakna ia hanya boleh melakukan satu perkara pada satu masa. Terdapat hanya satu timbunan panggilan, yang menyimpan fungsi yang akan dilaksanakan. Ini menjadikan kod segerak mudah, tetapi ia menimbulkan masalah untuk tugas seperti mengambil data daripada pelayan atau menetapkan tamat masa, yang mengambil masa untuk diselesaikan. Tanpa gelung acara, JavaScript akan tersekat menunggu tugasan ini dan tiada perkara lain yang akan berlaku.

Bagaimana Gelung Acara Berfungsi

1. Timbunan Panggilan:

Timbunan panggilan ialah tempat fungsi yang sedang dilaksanakan disimpan. JavaScript menambah dan mengalih keluar fungsi daripada tindanan panggilan semasa ia memproses kod.

2. Tugas Asynchronous Bermula:

Apabila tugas tak segerak seperti setTimeout, fetch atau Promise ditemui, JavaScript mewakilkan tugas itu kepada API Web penyemak imbas (seperti API Pemasa, API Rangkaian, dll.), yang mengendalikan tugas di latar belakang.

3. Tugas Bergerak ke Baris Tugas:

Setelah tugas tak segerak selesai (cth., pemasa selesai, atau data diterima daripada pelayan), panggilan balik (fungsi untuk mengendalikan hasil) dialihkan ke baris gilir tugas (atau baris gilir microtask dalam kes janji) .

4. Call Stack Menamatkan Pelaksanaan Semasa:

JavaScript terus melaksanakan kod segerak. Setelah tindanan panggilan kosong, gelung acara mengambil tugasan pertama daripada baris gilir tugas (atau baris gilir microtask) dan meletakkannya pada tindanan panggilan untuk pelaksanaan.

5. Ulang:

Proses ini berulang. Gelung peristiwa memastikan semua tugas tak segerak dikendalikan selepas tugas segerak semasa selesai.

Contoh

Sekarang kita memahami dengan lebih baik dan lebih jelas tentang cara gelung acara berfungsi, mari lihat beberapa contoh untuk mengukuhkan pemahaman kita.

Example 1: Timer with Promises and Event Loop

function exampleOne() {
  console.log("Start");

  setTimeout(() => {
    console.log("Timeout done");
  }, 1000);

  Promise.resolve().then(() => {
    console.log("Resolved");
  });

  console.log("End");
}

exampleOne();
Salin selepas log masuk

Output:

Start
End
Resolved
Timeout done
Salin selepas log masuk

Explanation:

  • Step 1: "Start" is printed (synchronous).
  • Step 2: setTimeout schedules the "Timeout done" message after 1 second (macrotask queue).
  • Step 3: A promise is resolved, and the "Resolved" message is pushed to the microtask queue.
  • Step 4: "End" is printed (synchronous).
  • Step 5: The call stack is now empty, so the microtask queue runs first, printing "Resolved".
  • Step 6: After 1 second, the macrotask queue runs, printing "Timeout done".

Example 2: Nested Promises and Timers

function exampleTwo() {
  console.log("Start");

  setTimeout(() => {
    console.log("Timer 1");
  }, 0);

  Promise.resolve().then(() => {
    console.log("Promise 1 Resolved");

    setTimeout(() => {
      console.log("Timer 2");
    }, 0);

    return Promise.resolve().then(() => {
      console.log("Promise 2 Resolved");
    });
  });

  console.log("End");
}

exampleTwo();
Salin selepas log masuk

Output:

Start
End
Promise 1 Resolved
Promise 2 Resolved
Timer 1
Timer 2
Salin selepas log masuk

Explanation:

  • Step 1: "Start" is printed (synchronous).
  • Step 2: The first setTimeout schedules "Timer 1" to run (macrotask queue).
  • Step 3: The promise resolves, and its callback is pushed to the microtask queue.
  • Step 4: "End" is printed (synchronous).
  • Step 5: The microtask queue runs first:
    • "Promise 1 Resolved" is printed.
    • "Timer 2" is scheduled (macrotask queue).
    • Another promise is resolved, and "Promise 2 Resolved" is printed.
  • Step 6: The macrotask queue is processed next:
    • "Timer 1" is printed.
    • "Timer 2" is printed last.

Example 3: Mixed Synchronous and Asynchronous Operations

function exampleThree() {
  console.log("Step 1: Synchronous");

  setTimeout(() => {
    console.log("Step 2: Timeout 1");
  }, 0);

  Promise.resolve().then(() => {
    console.log("Step 3: Promise 1 Resolved");

    Promise.resolve().then(() => {
      console.log("Step 4: Promise 2 Resolved");
    });

    setTimeout(() => {
      console.log("Step 5: Timeout 2");
    }, 0);
  });

  setTimeout(() => {
    console.log(
      "Step 6: Immediate (using setTimeout with 0 delay as fallback)"
    );
  }, 0);

  console.log("Step 7: Synchronous End");
}

exampleThree();
Salin selepas log masuk

Output:

Step 1: Synchronous
Step 7: Synchronous End
Step 3: Promise 1 Resolved
Step 4: Promise 2 Resolved
Step 2: Timeout 1
Step 6: Immediate (using setTimeout with 0 delay as fallback)
Step 5: Timeout 2
Salin selepas log masuk

Explanation:

  • Step 1: "Step 1: Synchronous" is printed (synchronous).
  • Step 2: The first setTimeout schedules "Step 2: Timeout 1" (macrotask queue).
  • Step 3: A promise resolves, scheduling "Step 3: Promise 1 Resolved" (microtask queue).
  • Step 4: Another synchronous log, "Step 7: Synchronous End", is printed.
  • Step 5: Microtask queue is processed:
    • "Step 3: Promise 1 Resolved" is printed.
    • "Step 4: Promise 2 Resolved" is printed (nested microtask).
  • Step 6: The macrotask queue is processed:
    • "Step 2: Timeout 1" is printed.
    • "Step 6: Immediate (using setTimeout with 0 delay as fallback)" is printed.
    • "Step 5: Timeout 2" is printed last.

Conclusion

In JavaScript, mastering synchronous and asynchronous operations, as well as understanding the event loop and how it handles tasks, is crucial for writing efficient and performant applications.

  • Synchronous functions run in sequence, blocking subsequent code until completion, while asynchronous functions (like setTimeout and promises) allow for non-blocking behavior, enabling efficient multitasking.
  • Microtasks (such as promises) have higher priority than macrotasks (such as setTimeout), meaning that the event loop processes microtasks immediately after the current execution, before moving to the macrotask queue.
  • The event loop is the core mechanism that allows JavaScript to handle asynchronous code by managing the execution order of tasks and ensuring that the call stack is clear before processing the next queue (microtask or macrotask).

The examples provided progressively illustrated the interaction between synchronous code, promises, timers, and the event loop. Understanding these concepts is key to mastering asynchronous programming in JavaScript, ensuring your code runs efficiently and avoids common pitfalls such as race conditions or unexpected execution orders.


Stay Updated and Connected

To ensure you don't miss any part of this series and to connect with me for more in-depth discussions on Software Development (Web, Server, Mobile or Scraping / Automation), push notifications, and other exciting tech topics, follow me on:

  • GitHub
  • Linkedin
  • X (Twitter)

Stay tuned and happy coding ?‍??

Atas ialah kandungan terperinci Memahami Pengaturcaraan Asynchronous dalam JavaScript: Panduan Pemula untuk Gelung Acara. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan