دنیای شگفت انگیز و وحشتناک برنامه نویسی ناهمزمان: یک رابطه عشق و نفرت

آه، برنامه نویسی ناهمزمان. شمشیر دولبه توسعه نرم افزار مدرن. مانند دادن قند به یک کودک نوپا است: پتانسیل باورنکردنی برای سرعت، اما اگر اشتباه از آن استفاده شود، دچار هرج و مرج خواهید شد. چه یک توسعهدهنده باتجربه باشید که یکی از شرایط مسابقه را رفع اشکال کرده است یا یک مبتدی کنجکاو که نمیداند چرا همه در مورد آن صحبت میکنند. async/await
، این پست برای شماست. بیایید به دنیای برنامهنویسی ناهمزمان شیرجه بزنیم، با مثالها، استعارهها و طنز فراوانی که شما را عاقل نگه میدارد.
برنامه نویسی ناهمزمان چیست؟
تصور کنید در یک کافی شاپ هستید. شما یک لاته سفارش میدهید، و بهجای اینکه پشت پیشخوان برای نوشیدنیتان منتظر بمانید (ممانعت باریستا از درست کردن قهوه دیگران)، مینشینید. باریستا در چندین سفارش به طور همزمان کار می کند و زمانی که لاته شما آماده است نام شما را صدا می کند. این، در اصل، برنامه نویسی ناهمزمان است: انجام کارهای بیشتر در حین انتظار.
در برنامه نویسی، کد سنکرون مانند باریستایی است که اصرار دارد یک سفارش را در یک زمان قبل از شروع سفارش بعدی تمام کند. کارآمد؟ نه واقعا. برنامه نویسی ناهمزمان به وظایف اجازه می دهد تا به طور مستقل اجرا شوند، عملکرد و پاسخگویی را بهبود می بخشد، به ویژه برای عملیات های سنگین I/O مانند تماس های API یا پرس و جوهای پایگاه داده.
چرا Go Async؟
-
عملکرد
در دنیای واقعی، شما نمیخواهید که کل صبحتان مسدود شود، زیرا دستگاه قهوه شما اصرار دارد که یک فنجان دم کنید. به طور مشابه، در نرم افزار، ما نمی توانیم همه چیز را فریز کنیم زیرا منتظر یک درخواست شبکه کند هستیم. -
تجربه کاربری
هیچ کس یک برنامه ثابت را دوست ندارد. اگر برنامه شما هر بار که دادهها را واکشی میکند قفل میشود، کاربران سریعتر از آنچه میتوانید بگویید «تأخیر»، رقبای Google را شروع میکنند. -
مقیاس پذیری
برنامه نویسی ناهمزمان به سرورها اجازه می دهد تا درخواست های بیشتری را با منابع کمتر انجام دهند. به آن به عنوان نرم افزاری معادل شعبده بازی فکر کنید: توپ های بیشتر در هوا، صفحات شکسته کمتر.
ایده اصلی: async/await
در جاوا اسکریپت، دارت، پایتون و بسیاری از زبان های دیگر، async/await
قند نحوی جادویی است که برنامه نویسی ناهمزمان را قابل هضم می کند. مثل داشتن یک دستیار شخصی است که زمزمه می کند: «هی، حالا نگران این موضوع نباش. وقتی تمام شد به شما اطلاع خواهم داد.»
در اینجا یک مثال در جاوا اسکریپت آمده است:
async function makeCoffee() {
console.log("Starting coffee...");
const coffee = await brewCoffee(); // Wait for coffee to brew
console.log("Coffee is ready: ", coffee);
}
function brewCoffee() {
return new Promise((resolve) => {
setTimeout(() => resolve("Latte"), 3000);
});
}
makeCoffee();
console.log("Meanwhile, you can read the newspaper.");
خروجی:
Starting coffee...
Meanwhile, you can read the newspaper.
Coffee is ready: Latte
توجه داشته باشید که چگونه برنامه هنگام دم کردن قهوه متوقف نمی شود. چندوظیفه ایه عزیزم
مشکلات رایج (و نحوه اجتناب از آنها)
1. هرم عذاب
قبل از async/await
، پاسخ به تماس ها عادی بود و کد به شکل زیر بود:
getUser((user) => {
getPosts(user.id, (posts) => {
getComments(posts[0].id, (comments) => {
console.log(comments);
});
});
});
این فقط یک هرم نیست. این برج بابل است. معرفی از async/await
این آشفتگی را صاف کرد:
const user = await getUser();
const posts = await getPosts(user.id);
const comments = await getComments(posts[0].id);
console.log(comments);
2. شرایط مسابقه
کد ناهمزمان عاشق مسابقه است. اگر مراقب نباشید، وظایف شما ممکن است روی انگشتان یکدیگر قرار گیرد:
let counter = 0;
async function increment() {
let temp = counter;
await new Promise((resolve) => setTimeout(resolve, 100));
counter = temp + 1;
}
await Promise.all([increment(), increment(), increment()]);
console.log(counter); // Not 3. Maybe 1. Maybe 2. Who knows?
رفع؟ همگام سازی مناسب:
const mutex = new Mutex(); // Use a library for this
await mutex.runExclusive(async () => {
let temp = counter;
await new Promise((resolve) => setTimeout(resolve, 100));
counter = temp + 1;
});
3. بن بست ها
بن بست زمانی است که دو کار به طور نامحدود روی یکدیگر منتظر می مانند. مثل دو راننده در یک تقاطع است که هر کدام با دست تکان می دهند تا اول برود. هیچ کس حرکت نمی کند.
مثال:
async function taskA() {
await lockB();
await lockA(); // Never happens
}
async function taskB() {
await lockA();
await lockB(); // Never happens
}
راه حل؟ از وابستگی های دایره ای خودداری کنید یا از وقفه های زمانی استفاده کنید.
نمونه های زندگی واقعی
1. فیدهای رسانه های اجتماعی
وقتی در توییتر اسکرول می کنید، هر توییت به یکباره بارگذاری نمی شود. در عوض، توییتها بهصورت ناهمزمان بارگیری میشوند و در حالی که برنامه دادههای بیشتری را در پسزمینه دریافت میکند، بازخورد فوری به شما میدهد.
2. خرید آنلاین
آیا تا به حال چیزی به سبد خرید خود اضافه کرده اید و آن را در زمان واقعی به روز کرده اید؟ این یک برنامه نویسی ناهمزمان است و تضمین می کند که نیازی نیست هر بار که یک جفت جوراب دیگر می خرید صفحه را به روز کنید.
رابطه عشق و نفرت
چرا آن را دوست دارم؟
- این قدرتمند و کارآمد است.
- این برنامه ها را سریعتر و پاسخگوتر می کند.
- وقتی کار می کند احساس جادویی دارد.
چرا متنفرم؟
- اشکال زدایی یک کابوس است.
- معرفی اشکالاتی که به سختی پیدا می شوند آسان است (سلام، شرایط مسابقه!).
- بار شناختی می تواند طاقت فرسا باشد.
افکار بسته
برنامه نویسی ناهمزمان مانند پختن یک غذای چند منظوره است. با برنامه ریزی و ابزار خوب، می توانید مانند یک سرآشپز حرفه ای این کار را انجام دهید. بدون آنها، آشپزخانه را آتش خواهید زد.
بنابراین هرج و مرج را در آغوش بگیرید، الگوها را بیاموزید و به یاد داشته باشید: وقتی همه چیز اشتباه می شود (و خواهد شد)، این پایان دنیا نیست. فقط یک روز دیگر در دنیای شگفت انگیز و وحشتناک برنامه نویسی.
اکنون به جلو بروید و async را فتح کنید! یا حداقل، آن را با ناامیدی کمتر رفع اشکال کنید.