Async ساخته شده آسان: فرو رفتن عمیق در JavaScript Callbacks، Promises و Async/Await

Summarize this content to 400 words in Persian Lang
جاوا اسکریپت یک زبان تک رشته ای است، به این معنی که می تواند یک کار را در یک زمان اجرا کند. با این حال، به لطف حلقه رویداد، می تواند به طور موثر عملیات ناهمزمان مانند واکشی داده ها، خواندن فایل ها یا مدیریت تعاملات کاربر را مدیریت کند و اطمینان حاصل کند که این کارها رشته اصلی را مسدود نمی کنند. با این حال، برنامه های کاربردی وب اغلب نیاز به انجام چندین عملیات به طور همزمان دارند، مانند واکشی داده ها از یک API، خواندن فایل ها، یا مدیریت تعاملات کاربر. برای انجام کارآمد این وظایف بدون مسدود کردن رشته اصلی، جاوا اسکریپت از تکنیک های برنامه نویسی ناهمزمان استفاده می کند. در این مقاله، به مفاهیم اصلی جاوا اسکریپت ناهمزمان خواهیم پرداخت: Callbacks، Promises و Async/Await. درک این مفاهیم برای ساخت برنامه های کاربردی وب واکنش گرا و با کارایی بالا ضروری است. ما هر مفهوم را گام به گام با مثال های دقیق بررسی خواهیم کرد تا به شما در درک نحوه اجرای موثر آنها کمک کنیم.
مقدمه ای بر برنامه نویسی ناهمزمان
برنامه نویسی ناهمزمان به کد شما اجازه می دهد در حالی که منتظر تکمیل عملیات طولانی مدت است، وظایف دیگری را انجام دهد. این برای ایجاد برنامه های وب پاسخگو بسیار مهم است. بیایید سه روش اصلی مورد استفاده در جاوا اسکریپت برای برنامه نویسی ناهمزمان را تجزیه کنیم:
تماس های تلفنی
وعده ها
Async/Await
هر روشی مزایا و معایب خاص خود را دارد. درک این روشها به شما کمک میکند رویکرد مناسبی را برای استفاده خاص خود انتخاب کنید.
تماس های تلفنی
Callbacks چیست؟
فراخوانی تابعی است که به عنوان آرگومان به تابع دیگری ارسال می شود و پس از تکمیل آن تابع اجرا می شود. Callback یک مفهوم اساسی در جاوا اسکریپت است که به طور گسترده در برنامه نویسی ناهمزمان، مدیریت رویداد و موارد دیگر استفاده می شود. Callback یکی از اولین روش هایی است که در جاوا اسکریپت برای مدیریت عملیات ناهمزمان استفاده می شود.
نمونه ای از تماس های تلفنی
بیایید با یک مثال ساده از یک تابع callback شروع کنیم:
function fetchData(callback) {
setTimeout(() => {
const data = { name: ‘John’, age: 30 };
callback(data);
}, 2000);
}
function displayData(data) {
console.log(`Name: ${data.name}, Age: ${data.age}`);
}
fetchData(displayData);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در این مثال، fetchData شبیه سازی یک عملیات ناهمزمان با استفاده از setTimeout. پس از اتمام عملیات، آن را فراخوانی می کند displayData عملکرد با داده های واکشی شده
مشکل با Callbacks: Callback Hell
در حالی که تماسهای برگشتی ساده هستند، میتوانند به کدهای عمیق تو در تو در هنگام برخورد با چندین عملیات ناهمزمان منجر شوند، پدیدهای که به عنوان «جهنم پاسخ به تماس» یا «هرم عذاب» شناخته میشود.
function fetchData(callback) {
setTimeout(() => {
const data = { name: ‘John’, age: 30 };
callback(data);
}, 2000);
}
function fetchMoreData(data, callback) {
setTimeout(() => {
data.job = ‘Developer’;
callback(data);
}, 2000);
}
function displayData(data) {
console.log(`Name: ${data.name}, Age: ${data.age}, Job: ${data.job}`);
}
fetchData((data) => {
fetchMoreData(data, (updatedData) => {
displayData(updatedData);
});
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
همانطور که می بینید، تماس های تو در تو، خواندن و نگهداری کد را سخت تر می کند.
وعده ها
وعده ها چیست؟
وعدههایی برای رسیدگی به مسائل مربوط به تماسهای تلفنی ارائه شد. وعده یک شی است که نشان دهنده تکمیل یا شکست نهایی یک عملیات ناهمزمان است. وعده ها دارای سه حالت هستند: در حال انتظار (وضعیت اولیه)، محقق شد (عملیات با موفقیت انجام شد)، و رد شد (عملیات ناموفق). این به شما امکان می دهد عملیات را زنجیره ای کنید و کد شما را خواناتر می کند.
نمونه ای از وعده ها
در اینجا نحوه بازنویسی مثال قبلی با استفاده از وعده ها آورده شده است:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
const data = { name: ‘John’, age: 30 };
resolve(data);
}, 2000);
});
}
function fetchMoreData(data) {
return new Promise((resolve) => {
setTimeout(() => {
data.job = ‘Developer’;
resolve(data);
}, 2000);
});
}
fetchData()
.then((data) => fetchMoreData(data))
.then((updatedData) => {
console.log(`Name: ${updatedData.name}, Age: ${updatedData.age}, Job: ${updatedData.job}`);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در این مثال، هر عملیات ناهمزمان یک وعده را برمیگرداند، و then روش برای زنجیره عملیات استفاده می شود.
رسیدگی به خطا با وعده ها
همچنین وعدهها رسیدگی به خطا را آسانتر میکنند. می توانید از روش catch برای رسیدگی به خطاها در زنجیره ای از عملیات ناهمزمان استفاده کنید:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // Simulate a success or failure
if (success) {
const data = { name: ‘John’, age: 30 };
resolve(data);
} else {
reject(‘Failed to fetch data’);
}
}, 2000);
});
}
fetchData()
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
Async/Await
Async/Await چیست؟
Async/Await یک قند نحوی است که بر اساس وعدهها ساخته شده است و در ES2017 (ES8) معرفی شده است. این امکان را به شما می دهد تا کدهای ناهمزمان را به روشی مشابه همزمان بنویسید، خوانایی را تا حد زیادی بهبود می بخشد و جریان کنترل را ساده می کند، به خصوص هنگامی که با چندین عملیات ناهمزمان سر و کار دارید. این به شما امکان می دهد کدهای ناهمزمان را به صورت همزمان بنویسید و خوانایی بیشتر و اشکال زدایی آن را آسان تر می کند.
مثالی از Async/Await
بیایید مثال مبتنی بر وعده خود را به استفاده از async/wait تبدیل کنیم:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
const data = { name: ‘John’, age: 30 };
resolve(data);
}, 2000);
});
}
function fetchMoreData(data) {
return new Promise((resolve) => {
setTimeout(() => {
data.job = ‘Developer’;
resolve(data);
}, 2000);
});
}
async function displayData() {
try {
const data = await fetchData();
const updatedData = await fetchMoreData(data);
console.log(`Name: ${updatedData.name}, Age: ${updatedData.age}, Job: ${updatedData.job}`);
} catch (error) {
console.error(error);
}
}
displayData();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
رسیدگی به خطا با Async/Await
رسیدگی به خطا در async/wait ساده است. می توانید از بلوک های try/catch برای رسیدگی به خطاها استفاده کنید:
async function displayData() {
try {
const data = await fetchData();
const updatedData = await fetchMoreData(data);
console.log(`Name: ${updatedData.name}, Age: ${updatedData.age}, Job: ${updatedData.job}`);
} catch (error) {
console.error(error);
}
}
displayData();
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مقایسه تماس ها، قول ها، و Async/Await
خوانایی
تماس های تلفنی: Callbacks: میتواند منجر به جهنم پاسخ به تماس شود، و خواندن، نگهداری و اشکالزدایی کد را دشوار میکند و اغلب منجر به کدهای مستعد خطا میشود.
وعده ها: بهبود خوانایی با اجازه دادن به شما برای زنجیره عملیات.
Async/Await: بهترین خوانایی را با امکان نوشتن کدهای ناهمزمان به صورت همزمان فراهم می کند.
رسیدگی به خطا
تماس های تلفنی: Callbacks: رسیدگی به خطاها دست و پا گیرتر است و اغلب شامل عبور اشیاء خطا از لایه های متعدد تماس است که منجر به کدهای پیچیده و سخت می شود. Promises و async/wait این فرآیند را با ارائه مکانیسمهای مدیریت خطای سادهتر و متمرکزتر سادهتر میکند.
وعده ها: مدیریت خطا را با روش catch ساده می کند.
Async/Await: مدیریت خطا را با بلوکهای try/catch سادهتر میکند.
موارد استفاده
تماس های تلفنی: مناسب برای عملیات ساده و تک ناهمزمان.
وعده ها: ایده آل برای زنجیره ای کردن چندین عملیات ناهمزمان.
Async/Await: بهترین گزینه برای عملیات پیچیده ناهمزمان و زمانی که خوانایی در اولویت است.
سوالات متداول
مزیت اصلی استفاده از Promises در مقابل Callback چیست؟
مزیت اصلی استفاده از وعدهها نسبت به تماسهای برگشتی، بهبود خوانایی و قابلیت نگهداری کد است. Promises از ساختار تودرتوی callbackها جلوگیری میکند و کد را خطیتر و راحتتر دنبال میکند.
آیا می توانم از Async/Await با مرورگرهای قدیمی استفاده کنم؟
Async/await در اکثر مرورگرهای مدرن پشتیبانی می شود. با این حال، برای مرورگرهای قدیمیتر، ممکن است لازم باشد از یک transpiler مانند Babel برای تبدیل کد async/wait به ES5 استفاده کنید.
چگونه می توانم چندین وعده را همزمان انجام دهم؟
می توانید استفاده کنید Promise.all برای رسیدگی به چندین وعده به طور همزمان به عنوان مثال:
const promise1 = fetchData();
const promise2 = fetchMoreData(data);
Promise.all([promise1, promise2])
.then((results) => {
const [data, moreData] = results;
console.log(data, moreData);
})
.catch((error) => {
console.error(error);
});
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
آیا Async/Await همیشه بهتر از وعده هاست؟
Async/wait عموماً خواناتر از وعدهها است، اما وعدهها میتوانند در سناریوهای خاص مناسبتر باشند، مانند زمانی که با چندین عملیات همزمان سروکار داریم.
چگونه یک عملیات ناهمزمان را لغو کنم؟
جاوا اسکریپت به صورت بومی از لغو وعده ها پشتیبانی نمی کند. با این حال، میتوانید از تکنیکهایی مانند AbortController برای واکشی درخواستها یا پیادهسازی منطق لغو خود استفاده کنید.
نتیجه گیری
برنامه نویسی ناهمزمان یکی از جنبه های اساسی جاوا اسکریپت است که به شما امکان می دهد برنامه های وب پاسخگو و کارآمد بسازید. درک تفاوتهای بین تماسهای برگشتی، وعدهها و غیر همگامسازی/انتظار برای نوشتن کد تمیز و قابل نگهداری بسیار مهم است. با تسلط بر تماسها، وعدهها و همگامسازی/انتظار، و درک زمان استفاده از هر کدام، میتوانید خوانایی، قابلیت نگهداری و عملکرد برنامههای خود را به میزان قابل توجهی بهبود بخشید. این دانش شما را قادر می سازد تا با اطمینان و کارآمدی با هر چالش ناهمزمانی مقابله کنید. چه تماسهای برگشتی را برای کارهای ساده انتخاب کنید، چه وعدههایی را برای عملیات زنجیرهای، یا همگامسازی/انتظار برای خوانایی را انتخاب کنید، تسلط بر این مفاهیم شما را به یک توسعهدهنده جاوا اسکریپت مؤثرتر تبدیل میکند.
جاوا اسکریپت یک زبان تک رشته ای است، به این معنی که می تواند یک کار را در یک زمان اجرا کند. با این حال، به لطف حلقه رویداد، می تواند به طور موثر عملیات ناهمزمان مانند واکشی داده ها، خواندن فایل ها یا مدیریت تعاملات کاربر را مدیریت کند و اطمینان حاصل کند که این کارها رشته اصلی را مسدود نمی کنند. با این حال، برنامه های کاربردی وب اغلب نیاز به انجام چندین عملیات به طور همزمان دارند، مانند واکشی داده ها از یک API، خواندن فایل ها، یا مدیریت تعاملات کاربر. برای انجام کارآمد این وظایف بدون مسدود کردن رشته اصلی، جاوا اسکریپت از تکنیک های برنامه نویسی ناهمزمان استفاده می کند. در این مقاله، به مفاهیم اصلی جاوا اسکریپت ناهمزمان خواهیم پرداخت: Callbacks، Promises و Async/Await. درک این مفاهیم برای ساخت برنامه های کاربردی وب واکنش گرا و با کارایی بالا ضروری است. ما هر مفهوم را گام به گام با مثال های دقیق بررسی خواهیم کرد تا به شما در درک نحوه اجرای موثر آنها کمک کنیم.
مقدمه ای بر برنامه نویسی ناهمزمان
برنامه نویسی ناهمزمان به کد شما اجازه می دهد در حالی که منتظر تکمیل عملیات طولانی مدت است، وظایف دیگری را انجام دهد. این برای ایجاد برنامه های وب پاسخگو بسیار مهم است. بیایید سه روش اصلی مورد استفاده در جاوا اسکریپت برای برنامه نویسی ناهمزمان را تجزیه کنیم:
- تماس های تلفنی
- وعده ها
- Async/Await
هر روشی مزایا و معایب خاص خود را دارد. درک این روشها به شما کمک میکند رویکرد مناسبی را برای استفاده خاص خود انتخاب کنید.
تماس های تلفنی
Callbacks چیست؟
فراخوانی تابعی است که به عنوان آرگومان به تابع دیگری ارسال می شود و پس از تکمیل آن تابع اجرا می شود. Callback یک مفهوم اساسی در جاوا اسکریپت است که به طور گسترده در برنامه نویسی ناهمزمان، مدیریت رویداد و موارد دیگر استفاده می شود. Callback یکی از اولین روش هایی است که در جاوا اسکریپت برای مدیریت عملیات ناهمزمان استفاده می شود.
نمونه ای از تماس های تلفنی
بیایید با یک مثال ساده از یک تابع callback شروع کنیم:
function fetchData(callback) {
setTimeout(() => {
const data = { name: 'John', age: 30 };
callback(data);
}, 2000);
}
function displayData(data) {
console.log(`Name: ${data.name}, Age: ${data.age}`);
}
fetchData(displayData);
در این مثال، fetchData
شبیه سازی یک عملیات ناهمزمان با استفاده از setTimeout
. پس از اتمام عملیات، آن را فراخوانی می کند displayData
عملکرد با داده های واکشی شده
مشکل با Callbacks: Callback Hell
در حالی که تماسهای برگشتی ساده هستند، میتوانند به کدهای عمیق تو در تو در هنگام برخورد با چندین عملیات ناهمزمان منجر شوند، پدیدهای که به عنوان «جهنم پاسخ به تماس» یا «هرم عذاب» شناخته میشود.
function fetchData(callback) {
setTimeout(() => {
const data = { name: 'John', age: 30 };
callback(data);
}, 2000);
}
function fetchMoreData(data, callback) {
setTimeout(() => {
data.job = 'Developer';
callback(data);
}, 2000);
}
function displayData(data) {
console.log(`Name: ${data.name}, Age: ${data.age}, Job: ${data.job}`);
}
fetchData((data) => {
fetchMoreData(data, (updatedData) => {
displayData(updatedData);
});
});
همانطور که می بینید، تماس های تو در تو، خواندن و نگهداری کد را سخت تر می کند.
وعده ها
وعده ها چیست؟
وعدههایی برای رسیدگی به مسائل مربوط به تماسهای تلفنی ارائه شد. وعده یک شی است که نشان دهنده تکمیل یا شکست نهایی یک عملیات ناهمزمان است. وعده ها دارای سه حالت هستند: در حال انتظار (وضعیت اولیه)، محقق شد (عملیات با موفقیت انجام شد)، و رد شد (عملیات ناموفق). این به شما امکان می دهد عملیات را زنجیره ای کنید و کد شما را خواناتر می کند.
نمونه ای از وعده ها
در اینجا نحوه بازنویسی مثال قبلی با استفاده از وعده ها آورده شده است:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
const data = { name: 'John', age: 30 };
resolve(data);
}, 2000);
});
}
function fetchMoreData(data) {
return new Promise((resolve) => {
setTimeout(() => {
data.job = 'Developer';
resolve(data);
}, 2000);
});
}
fetchData()
.then((data) => fetchMoreData(data))
.then((updatedData) => {
console.log(`Name: ${updatedData.name}, Age: ${updatedData.age}, Job: ${updatedData.job}`);
});
در این مثال، هر عملیات ناهمزمان یک وعده را برمیگرداند، و then
روش برای زنجیره عملیات استفاده می شود.
رسیدگی به خطا با وعده ها
همچنین وعدهها رسیدگی به خطا را آسانتر میکنند. می توانید از روش catch برای رسیدگی به خطاها در زنجیره ای از عملیات ناهمزمان استفاده کنید:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // Simulate a success or failure
if (success) {
const data = { name: 'John', age: 30 };
resolve(data);
} else {
reject('Failed to fetch data');
}
}, 2000);
});
}
fetchData()
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});
Async/Await
Async/Await چیست؟
Async/Await یک قند نحوی است که بر اساس وعدهها ساخته شده است و در ES2017 (ES8) معرفی شده است. این امکان را به شما می دهد تا کدهای ناهمزمان را به روشی مشابه همزمان بنویسید، خوانایی را تا حد زیادی بهبود می بخشد و جریان کنترل را ساده می کند، به خصوص هنگامی که با چندین عملیات ناهمزمان سر و کار دارید. این به شما امکان می دهد کدهای ناهمزمان را به صورت همزمان بنویسید و خوانایی بیشتر و اشکال زدایی آن را آسان تر می کند.
مثالی از Async/Await
بیایید مثال مبتنی بر وعده خود را به استفاده از async/wait تبدیل کنیم:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
const data = { name: 'John', age: 30 };
resolve(data);
}, 2000);
});
}
function fetchMoreData(data) {
return new Promise((resolve) => {
setTimeout(() => {
data.job = 'Developer';
resolve(data);
}, 2000);
});
}
async function displayData() {
try {
const data = await fetchData();
const updatedData = await fetchMoreData(data);
console.log(`Name: ${updatedData.name}, Age: ${updatedData.age}, Job: ${updatedData.job}`);
} catch (error) {
console.error(error);
}
}
displayData();
رسیدگی به خطا با Async/Await
رسیدگی به خطا در async/wait ساده است. می توانید از بلوک های try/catch برای رسیدگی به خطاها استفاده کنید:
async function displayData() {
try {
const data = await fetchData();
const updatedData = await fetchMoreData(data);
console.log(`Name: ${updatedData.name}, Age: ${updatedData.age}, Job: ${updatedData.job}`);
} catch (error) {
console.error(error);
}
}
displayData();
مقایسه تماس ها، قول ها، و Async/Await
خوانایی
- تماس های تلفنی: Callbacks: میتواند منجر به جهنم پاسخ به تماس شود، و خواندن، نگهداری و اشکالزدایی کد را دشوار میکند و اغلب منجر به کدهای مستعد خطا میشود.
- وعده ها: بهبود خوانایی با اجازه دادن به شما برای زنجیره عملیات.
- Async/Await: بهترین خوانایی را با امکان نوشتن کدهای ناهمزمان به صورت همزمان فراهم می کند.
رسیدگی به خطا
- تماس های تلفنی: Callbacks: رسیدگی به خطاها دست و پا گیرتر است و اغلب شامل عبور اشیاء خطا از لایه های متعدد تماس است که منجر به کدهای پیچیده و سخت می شود. Promises و async/wait این فرآیند را با ارائه مکانیسمهای مدیریت خطای سادهتر و متمرکزتر سادهتر میکند.
- وعده ها: مدیریت خطا را با روش catch ساده می کند.
- Async/Await: مدیریت خطا را با بلوکهای try/catch سادهتر میکند.
موارد استفاده
- تماس های تلفنی: مناسب برای عملیات ساده و تک ناهمزمان.
- وعده ها: ایده آل برای زنجیره ای کردن چندین عملیات ناهمزمان.
- Async/Await: بهترین گزینه برای عملیات پیچیده ناهمزمان و زمانی که خوانایی در اولویت است.
سوالات متداول
مزیت اصلی استفاده از Promises در مقابل Callback چیست؟
مزیت اصلی استفاده از وعدهها نسبت به تماسهای برگشتی، بهبود خوانایی و قابلیت نگهداری کد است. Promises از ساختار تودرتوی callbackها جلوگیری میکند و کد را خطیتر و راحتتر دنبال میکند.
آیا می توانم از Async/Await با مرورگرهای قدیمی استفاده کنم؟
Async/await در اکثر مرورگرهای مدرن پشتیبانی می شود. با این حال، برای مرورگرهای قدیمیتر، ممکن است لازم باشد از یک transpiler مانند Babel برای تبدیل کد async/wait به ES5 استفاده کنید.
چگونه می توانم چندین وعده را همزمان انجام دهم؟
می توانید استفاده کنید Promise.all
برای رسیدگی به چندین وعده به طور همزمان به عنوان مثال:
const promise1 = fetchData();
const promise2 = fetchMoreData(data);
Promise.all([promise1, promise2])
.then((results) => {
const [data, moreData] = results;
console.log(data, moreData);
})
.catch((error) => {
console.error(error);
});
آیا Async/Await همیشه بهتر از وعده هاست؟
Async/wait عموماً خواناتر از وعدهها است، اما وعدهها میتوانند در سناریوهای خاص مناسبتر باشند، مانند زمانی که با چندین عملیات همزمان سروکار داریم.
چگونه یک عملیات ناهمزمان را لغو کنم؟
جاوا اسکریپت به صورت بومی از لغو وعده ها پشتیبانی نمی کند. با این حال، میتوانید از تکنیکهایی مانند AbortController برای واکشی درخواستها یا پیادهسازی منطق لغو خود استفاده کنید.
نتیجه گیری
برنامه نویسی ناهمزمان یکی از جنبه های اساسی جاوا اسکریپت است که به شما امکان می دهد برنامه های وب پاسخگو و کارآمد بسازید. درک تفاوتهای بین تماسهای برگشتی، وعدهها و غیر همگامسازی/انتظار برای نوشتن کد تمیز و قابل نگهداری بسیار مهم است. با تسلط بر تماسها، وعدهها و همگامسازی/انتظار، و درک زمان استفاده از هر کدام، میتوانید خوانایی، قابلیت نگهداری و عملکرد برنامههای خود را به میزان قابل توجهی بهبود بخشید. این دانش شما را قادر می سازد تا با اطمینان و کارآمدی با هر چالش ناهمزمانی مقابله کنید. چه تماسهای برگشتی را برای کارهای ساده انتخاب کنید، چه وعدههایی را برای عملیات زنجیرهای، یا همگامسازی/انتظار برای خوانایی را انتخاب کنید، تسلط بر این مفاهیم شما را به یک توسعهدهنده جاوا اسکریپت مؤثرتر تبدیل میکند.