مفهوم برنامهنویسی همزمان و ناهمزمان در جاوا اسکریپت: تفاوتها، مثالها و کاربردها
برنامهنویسی همزمان و ناهمزمان دو مفهوم کلیدی در توسعه نرمافزار هستند که به شما امکان میدهند تا نحوه اجرای کد را مدیریت کنید. در جاوا اسکریپت، برنامهنویسی ناهمزمان به دلیل ویژگیهای غیرهمزمان زبان و نیاز به کار با ورودی/خروجی (I/O) و درخواستهای شبکه، نقش بسیار مهمی دارد. در این مقاله، به بررسی مفاهیم همزمان و ناهمزمان، تفاوتها و نحوه مدیریت آنها در جاوا اسکریپت خواهیم پرداخت.
مقدمهای بر برنامهنویسی همزمان و ناهمزمان
برنامهنویسی همزمان
در برنامهنویسی همزمان، کد به ترتیب و به صورت خطی اجرا میشود. این بدان معنی است که برنامه به ترتیب دستورات را اجرا میکند و برای هر دستور تا زمانی که دستور قبلی تمام نشود، صبر میکند.
مثال: برنامهنویسی همزمان
function fetchData() {
console.log("Fetching data...");
// شبیهسازی تأخیر در پردازش
for (let i = 0; i < 1e9; i++) {}
console.log("Data fetched.");
}
console.log("Start");
fetchData();
console.log("End");
در این مثال:
-
fetchData() به صورت همزمان اجرا میشود و اجرای "End" تا زمانی که fetchData() تمام نشده باشد، متوقف میشود.
برنامهنویسی ناهمزمان
در برنامهنویسی ناهمزمان، کد میتواند بدون انتظار برای اتمام یک عملیات، به اجرای سایر عملیاتها ادامه دهد. این مفهوم برای برنامههای با تعاملات ورودی/خروجی، مانند درخواستهای شبکه، بسیار مفید است.
مثال: برنامهنویسی ناهمزمان
console.log("Start");
setTimeout(() => {
console.log("Data fetched.");
}, 2000); // شبیهسازی تأخیر در پردازش به مدت 2 ثانیه
console.log("End");
در این مثال:
-
setTimeout یک عملیات ناهمزمان است که پس از مدت زمان مشخص، تابع را اجرا میکند.
-
"End" قبل از "Data fetched" چاپ میشود، زیرا setTimeout برنامه را متوقف نمیکند.
مفهوم Event Loop و Callback Queue
Event Loop
Event Loop یا حلقه رویداد، مکانیزمی است که به جاوا اسکریپت اجازه میدهد تا برنامهنویسی ناهمزمان را مدیریت کند. این مکانیزم وظیفه دارد که نوبتهای مختلف از کد را مدیریت کند و اطمینان حاصل کند که عملیاتهای ناهمزمان به درستی اجرا شوند.
نحوه عملکرد Event Loop:
-
Stack (پشته): جایی که توابع در حال اجرا قرار دارند.
-
Callback Queue (صف بازخورد): جایی که توابع ناهمزمان و بازخوردها (مانند توابع از setTimeout) قرار میگیرند.
-
Event Loop: حلقهای که از پشته خالی بودن و وجود بازخوردها در صف بازخورد را بررسی میکند و در صورت وجود، آنها را به پشته اضافه میکند.
Callback Queue
Callback Queue جایی است که توابعی که باید به طور ناهمزمان اجرا شوند، در آن قرار میگیرند. پس از پایان اجرای توابع موجود در پشته، Event Loop این توابع را از صف بازخورد برداشته و به پشته اضافه میکند.
مثال: نحوه کارکرد Event Loop
console.log("Start");
setTimeout(() => {
console.log("Timeout callback");
}, 0);
console.log("End");
در این مثال:
-
"Start" و "End" به ترتیب چاپ میشوند.
-
توابع setTimeout در صف بازخورد قرار میگیرند و پس از اجرای دستورات همزمان، "Timeout callback" چاپ میشود.
Promises و نحوه کارکرد آنها
معرفی Promises
Promises (وعدهها) برای مدیریت عملیاتهای ناهمزمان طراحی شدهاند و به شما این امکان را میدهند که کدهای غیرهمزمان را به شکل قابلفهمتر و مدیریتپذیرتر بنویسید. Promiseها وضعیتهای مختلفی دارند:
-
Pending: وضعیت اولیه، وقتی که عملیات هنوز در حال انجام است.
-
Fulfilled: زمانی که عملیات به درستی تمام شده است.
-
Rejected: زمانی که عملیات با خطا مواجه شده است.
ساختار Promise
const myPromise = new Promise((resolve, reject) => {
// عملیات ناهمزمان
setTimeout(() => {
resolve("Success!");
}, 2000);
});
myPromise.then(result => {
console.log(result); // Output: Success!
}).catch(error => {
console.log(error);
});
استفاده از async و await
async و await به شما این امکان را میدهند که کدهای ناهمزمان را به شیوهای همزمانتر بنویسید و از Promiseها به شکل سادهتری استفاده کنید.
مثال: استفاده از async و await
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function example() {
console.log("Start");
await delay(2000); // منتظر 2 ثانیه
console.log("End");
}
example();
در این مثال:
-
تابع delay یک Promise را بازمیگرداند که بعد از مدت زمان مشخص شده، حل میشود.
-
با استفاده از await, تابع example منتظر میماند تا Promise به حالت Fulfilled برسد و سپس ادامه مییابد.
مدیریت خطاها در Promises و async/await
مدیریت خطاها در Promises
const myPromise = new Promise((resolve, reject) => {
// شبیهسازی خطا
reject("Error occurred!");
});
myPromise.then(result => {
console.log(result);
}).catch(error => {
console.log(error); // Output: Error occurred!
});
مدیریت خطاها در async/await
async function example() {
try {
await delay(2000);
throw new Error("Something went wrong!");
} catch (error) {
console.log(error.message); // Output: Something went wrong!
}
}
example();
تفاوت بین Callback، Promises و async/await
Callbacks
Callbacks سادهترین و قدیمیترین روش برای مدیریت عملیاتهای ناهمزمان هستند. معایب آنها شامل معضل "Callback Hell" است که میتواند کد را پیچیده و غیرقابلخوانا کند.
Promises
Promises بهبودهایی نسبت به Callbacks ارائه میدهند و کدهای ناهمزمان را با استفاده از زنجیرههای then و catch سادهتر میکنند. آنها کمک میکنند تا از معضل Callback Hell اجتناب شود.
async/await
async/await بیشتر شبیه به کدهای همزمان است و به شما این امکان را میدهد که از مزایای Promises بدون پیچیدگی استفاده کنید. با استفاده از async/await میتوانید کدهای ناهمزمان را به روشی خواناتر و مدیریتیتر بنویسید.
نتیجهگیری
درک مفاهیم برنامهنویسی همزمان و ناهمزمان برای توسعه نرمافزارهای مدرن بسیار حیاتی است. جاوا اسکریپت با استفاده از Event Loop، Callbacks، Promises و async/await ابزارهای قدرتمندی برای مدیریت عملیاتهای ناهمزمان فراهم میکند. با استفاده از این ابزارها میتوانید برنامههای کارآمد و مقیاسپذیری بنویسید که به خوبی با عملیاتهای ورودی/خروجی و درخواستهای شبکه تعامل دارند. یادگیری نحوه استفاده مؤثر از این ابزارها به شما کمک خواهد کرد تا کدهای بهتری بنویسید و مشکلات مربوط به عملکرد و مدیریت ناهمزمانی را به طور مؤثری حل کنید.
پرسش و پاسخ
نظری یافت نشد
برای ارسال نظر ابتدا وارد شوید