Apabila saya mula-mula menemui JavaScript tak segerak, saya bergelut dengan panggilan balik dan tidak tahu cara Promises berfungsi di bawah hud. Lama kelamaan, pembelajaran tentang Janji dan async/menunggu mengubah pendekatan saya terhadap pengekodan, menjadikannya lebih mudah diurus. Dalam blog ini, kami akan meneroka corak async ini langkah demi langkah, mendedahkan cara ia boleh menyelaraskan proses pembangunan anda dan menjadikan kod anda lebih bersih dan lebih cekap. Mari selami dan temui konsep ini bersama-sama!
Mempelajari JavaScript tak segerak adalah penting untuk pembangunan web moden. Ia membolehkan anda mengendalikan tugas seperti permintaan API dengan cekap, memastikan aplikasi anda responsif dan pantas. Menguasai teknik async, seperti Janji dan async/menunggu, adalah penting bukan sahaja untuk membina aplikasi berskala tetapi juga untuk berjaya dalam temu duga kerja JavaScript, yang memahami konsep ini selalunya menjadi tumpuan utama. Dengan menguasai JavaScript tak segerak, anda akan meningkatkan kemahiran pengekodan anda dan lebih bersedia untuk menghadapi cabaran dunia sebenar.
Corak tak segerak dalam JavaScript ialah teknik yang digunakan untuk mengendalikan tugasan yang mengambil masa, seperti mengambil data daripada pelayan, tanpa membekukan aplikasi. Pada mulanya, pembangun menggunakan panggilan balik untuk mengurus tugasan ini, tetapi pendekatan ini sering membawa kepada kod yang rumit dan sukar dibaca, yang dikenali sebagai "neraka panggilan balik." Untuk memudahkan perkara ini, Promises telah diperkenalkan, menyediakan cara yang lebih bersih untuk mengendalikan operasi tak segerak dengan merantai tindakan dan mengendalikan ralat dengan lebih anggun. Evolusi diteruskan dengan async/wait, yang membolehkan anda menulis kod asynchronous yang kelihatan dan berkelakuan lebih seperti kod segerak, menjadikannya lebih mudah untuk dibaca dan diselenggara. Corak ini penting untuk membina aplikasi yang cekap, responsif dan asas dalam pembangunan JavaScript moden. Kami akan meneroka konsep ini dengan lebih terperinci sepanjang blog ini.
Panggil balik ialah fungsi yang anda hantar sebagai hujah kepada fungsi lain, dengan tujuan bahawa fungsi penerima akan melaksanakan panggilan balik pada satu ketika. Ini berguna untuk senario di mana anda ingin memastikan beberapa kod berjalan selepas tugas tertentu selesai, seperti selepas mengambil data daripada pelayan atau menyelesaikan pengiraan.
Cara Panggilan Balik Berfungsi:
contoh 1
function fetchData(callback) { // Simulate fetching data with a delay setTimeout(() => { const data = "Data fetched"; callback(data); // Call the callback function with the fetched data }, 1000); } function processData(data) { console.log("Processing:", data); } fetchData(processData); // fetchData will call processData with the data
contoh 2
// Function that adds two numbers and uses a callback to return the result function addNumbers(a, b, callback) { const result = a + b; callback(result); // Call the callback function with the result } // Callback function to handle the result function displayResult(result) { console.log("The result is:", result); } // Call addNumbers with the displayResult callback addNumbers(5, 3, displayResult);
Nota: Saya rasa panggilan balik berkesan untuk mengendalikan operasi tak segerak, tetapi berhati-hati: apabila kerumitan kod anda meningkat, terutamanya dengan panggilan balik bersarang, anda mungkin menghadapi masalah yang dikenali sebagai neraka panggil balik. Isu ini timbul apabila panggilan balik sangat bersarang antara satu sama lain, membawa kepada masalah kebolehbacaan dan menjadikan kod lebih sukar untuk dikekalkan.
Neraka Panggilan Balik (juga dikenali sebagai Pyramid of Doom) merujuk kepada situasi di mana anda mempunyai berbilang panggilan balik bersarang. Ini berlaku apabila anda perlu melakukan beberapa operasi tak segerak dalam turutan dan setiap operasi bergantung pada operasi sebelumnya.
cth. Ini mewujudkan struktur "piramid" yang sukar dibaca dan diselenggara.
fetchData(function(data1) { processData1(data1, function(result1) { processData2(result1, function(result2) { processData3(result2, function(result3) { console.log("Final result:", result3); }); }); }); });
Isu dengan Neraka Panggilan Balik:
Apabila bekerja dengan panggil balik, adalah perkara biasa untuk menggunakan corak yang dikenali sebagai panggilan balik ralat-pertama. Dalam corak ini, fungsi panggil balik mengambil ralat sebagai hujah pertamanya. Jika tiada ralat, hujah pertama biasanya batal atau tidak ditentukan dan hasil sebenar disediakan sebagai hujah kedua.
function fetchData(callback) { setTimeout(() => { const error = null; // Or `new Error("Some error occurred")` if there's an error const data = "Data fetched"; callback(error, data); // Pass error and data to the callback }, 1000); } function processData(error, data) { if (error) { console.error("Error:", error); return; } console.log("Processing:", data); } fetchData(processData); // `processData` will handle both error and data
Nota: Selepas panggilan balik, Promises diperkenalkan untuk mengendalikan proses tak segerak dalam JavaScript. Kini kita akan menyelam lebih dalam ke dalam Promises dan meneroka cara ia berfungsi di bawah hud.
Janji ialah objek yang mewakili penyiapan (atau kegagalan) operasi tak segerak dan nilai yang terhasil. Ia menyediakan cara yang lebih bersih untuk mengendalikan kod tak segerak berbanding dengan panggilan balik.
Tujuan Janji:
A Promise can be in one of three states:
Note: If you want to explore more, you should check out Understand How Promises Work Under the Hood where I discuss how promises work under the hood.
example 1
// Creating a new promise const myPromise = new Promise((resolve, reject) => { const success = true; // Simulate success or failure if (success) { resolve("Operation successful!"); // If successful, call resolve } else { reject("Operation failed!"); // If failed, call reject } }); // Using the promise myPromise .then((message) => { console.log(message); // Handle the successful case }) .catch((error) => { console.error(error); // Handle the error case });
example 2
const examplePromise = new Promise((resolve, reject) => { setTimeout(() => { const success = Math.random() > 0.5; // Randomly succeed or fail if (success) { resolve("Success!"); } else { reject("Failure."); } }, 1000); }); console.log("Promise state: Pending..."); // To check the state, you would use `.then()` or `.catch()` examplePromise .then((message) => { console.log("Promise state: Fulfilled"); console.log(message); }) .catch((error) => { console.log("Promise state: Rejected"); console.error(error); });
Chaining allows you to perform multiple asynchronous operations in sequence, with each step depending on the result of the previous one.
Chaining promises is a powerful feature of JavaScript that allows you to perform a sequence of asynchronous operations where each step depends on the result of the previous one. This approach is much cleaner and more readable compared to deeply nested callbacks.
Promise chaining involves connecting multiple promises in a sequence. Each promise in the chain executes only after the previous promise is resolved, and the result of each promise can be passed to the next step in the chain.
function step1() { return new Promise((resolve) => { setTimeout(() => resolve("Step 1 completed"), 1000); }); } function step2(message) { return new Promise((resolve) => { setTimeout(() => resolve(message + " -> Step 2 completed"), 1000); }); } function step3(message) { return new Promise((resolve) => { setTimeout(() => resolve(message + " -> Step 3 completed"), 1000); }); } // Chaining the promises step1() .then(result => step2(result)) .then(result => step3(result)) .then(finalResult => console.log(finalResult)) .catch(error => console.error("Error:", error));
Disadvantages of Chaining:
While chaining promises improves readability compared to nested callbacks, it can still become unwieldy if the chain becomes too long or complex. This can lead to readability issues similar to those seen with callback hell.
Note: To address these challenges, async and await were introduced to provide an even more readable and straightforward way to handle asynchronous operations in JavaScript.
async and await are keywords introduced in JavaScript to make handling asynchronous code more readable and easier to work with.
async function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve("Data fetched"); }, 1000); }); } async function getData() { const data = await fetchData(); // Wait for fetchData to resolve console.log(data); // Logs "Data fetched" } getData();
1. Async Functions Always Return a Promise:
No matter what you return from an async function, it will always be wrapped in a promise. For example:
async function example() { return "Hello"; } example().then(console.log); // Logs "Hello"
Even though example() returns a string, it is automatically wrapped in a promise.
2. Await Pauses Execution:
The await keyword pauses the execution of an async function until the promise it is waiting for resolves.
async function example() { console.log("Start"); const result = await new Promise((resolve) => { setTimeout(() => { resolve("Done"); }, 1000); }); console.log(result); // Logs "Done" after 1 second } example();
In this example:
Handling errors with async/await is done using try/catch blocks, which makes error handling more intuitive compared to promise chains.
async function fetchData() { throw new Error("Something went wrong!"); } async function getData() { try { const data = await fetchData(); console.log(data); } catch (error) { console.error("Error:", error.message); // Logs "Error: Something went wrong!" } } getData();
With Promises, you handle errors using .catch():
fetchData() .then(data => console.log(data)) .catch(error => console.error("Error:", error.message));
Using async/await with try/catch often results in cleaner and more readable code.
You can use async/await with existing promise-based functions seamlessly.
example
function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve("Data fetched"); }, 1000); }); } async function getData() { const data = await fetchData(); // Wait for the promise to resolve console.log(data); // Logs "Data fetched" } getData();
Best Practices:
async and wait menyediakan cara yang lebih bersih dan mudah dibaca untuk mengendalikan operasi tak segerak berbanding dengan rantaian janji tradisional dan panggil balik. Dengan membenarkan anda menulis kod tak segerak yang kelihatan dan berkelakuan seperti kod segerak, ia memudahkan logik kompleks dan meningkatkan pengendalian ralat dengan blok cuba/tangkap. Menggunakan async/menunggu dengan janji menghasilkan kod yang lebih mudah diselenggara dan difahami.
Atas ialah kandungan terperinci Menguasai Corak Async JavaScript: Daripada Panggilan Balik kepada Async/Await. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!