جاوا اسکریپت ناهمزمان: درک وعده ها – انجمن DEV

جاوا اسکریپت ناهمزمان روشی برای اجرای کد است که به چندین کار اجازه می دهد تا به طور همزمان بدون مسدود کردن رشته اصلی اجرا شوند. این به ویژه در هنگام برخورد با عملیات طولانی مدت، مانند درخواست های شبکه یا ورودی/خروجی فایل، مفید است.
یکی از محبوبترین روشهای پیادهسازی کد ناهمزمان در جاوا اسکریپت، استفاده از وعدهها است. در این پست، ما به بررسی اینکه وعده ها چیست، چگونه کار می کنند و برخی از مشکلات رایجی که ممکن است هنگام استفاده از آنها با آنها مواجه شوید، خواهیم پرداخت.
وعده ها چیست؟
یک وعده شیئی است که نشان دهنده تکمیل (یا شکست) نهایی یک عملیات ناهمزمان است. این یک مکان نگهدار برای مقداری است که ممکن است هنوز در دسترس نباشد، اما در مقطعی در آینده در دسترس خواهد بود.
وعده ها سه حالت دارند:
- انتظار: حالت اولیه. وعده نه وفا می شود و نه رد می شود.
- برآورده شد: عملیات با موفقیت به پایان رسید، و وعده اکنون یک مقدار نتیجه دارد.
- رد شد: عملیات ناموفق بود و وعده اکنون دارای مقدار خطا است.
ایجاد وعده ها
وعده ها را می توان با استفاده از Promise
سازنده سازنده یک آرگومان واحد می گیرد که تابعی است که عملیات ناهمزمان را تعریف می کند.
const promise = new Promise((resolve, reject) => {
// Perform some asynchronous operation
// If it succeeds, call resolve with the resulting value
// If it fails, call reject with an error object
});
را resolve
و reject
توابع توسط Promise
سازنده، و برای انتقال وعده از حالت در حال انتظار به حالت انجام شده یا رد شده استفاده می شوند.
در اینجا یک مثال از یک وعده است که پس از یک ثانیه تاخیر به یک رشته حل می شود:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello, world!');
}, 1000);
});
وعده های مصرفی
هنگامی که یک وعده ایجاد شد، می توانید نتیجه آن را با استفاده از آن مصرف کنید .then()
روش. این روش دو آرگومان دارد: یک تابع callback برای رسیدگی به تحقق وعده و یک تابع callback اختیاری برای رسیدگی به رد وعده.
promise.then(
(result) => {
console.log(result); // "Hello, world!"
},
(error) => {
console.error(error);
}
);
اگر وعده محقق شود، اولین تابع فراخوانی با مقدار حاصل به عنوان آرگومان فراخوانی می شود. اگر قول رد شود، تابع دوم فراخوانی با آرگومان شی خطا فراخوانی می شود.
وعده های زنجیره ای
یکی از مزایای کلیدی وعدهها این است که میتوان آنها را به هم متصل کرد و امکان ساخت عملیات ناهمزمان پیچیدهتری را فراهم کرد.
را .then()
متد یک وعده جدید را برمی گرداند، که می تواند برای زنجیره های اضافی استفاده شود .then()
مواد و روش ها. هر یک .then()
متد می تواند عملیات ناهمزمان خود را انجام دهد و نتیجه آن به بعدی منتقل می شود .then()
روش در زنجیره
const promise = new Promise < any > ((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 1000);
});
promise
.then((result) => {
// Multiply the result by 2
return result * 2;
})
.then((result) => {
// Add 5 to the result
return result + 5;
})
.then((result) => {
console.log(result); // 25
});
در این مثال، قول به مقدار حل می شود 10
. اولین .then()
متد این مقدار را در 2 ضرب می کند و نتیجه می شود 20
. دومین .then()
متد 5 را به این مقدار اضافه می کند و در نتیجه 25
.
وعدهها به ما امکان میدهند عملیاتها را زنجیرهای کنیم و کدهای پاکتر و خواناتر را ممکن میسازند. را catch()
روش را نیز می توان با زنجیر کرد then()
روش به شرح زیر –
myPromise
.then(result => {
// Handle the resolved value
})
.catch(error => {
// Handle the rejected error
});
رسیدگی به وعده های متعدد
وقتی با چندین وعده سروکار داریم، می توانیم استفاده کنیم Promise.all()
یا Promise.race()
برای هماهنگ کردن اجرای آنها:
Promise.all(): منتظر می ماند تا همه وعده ها محقق شوند و مجموعه ای از نتایج را برمی گرداند.
Promise.race(): به محض رفع یا رد هر یک از وعده ها حل یا رد می شود.
const promises = [promise1, promise2, promise3];
Promise.all(promises)
.then(results => {
// Handle the array of results
})
.catch(error => {
// Handle any errors
});
مشکلات مربوط به وعده ها
در حالی که وعده ها ابزار قدرتمندی برای برنامه نویسی ناهمزمان هستند، اما اگر به درستی استفاده نشوند، می توانند منبع ناامیدی نیز باشند.
1. جهنم برگشت به تماس
یکی از مشکلات استفاده از وعده ها این است که می تواند منجر به پدیده ای به نام “جهنم برگشت به تماس” شود. این زمانی اتفاق میافتد که چندین لایه تماس تو در تو داشته باشید و خواندن و نگهداری کد را دشوار میکند.
getData().then(data => {
processData(data).then(result => {
displayResult(result).then(() => {
// perform final task
}).catch(error => {
// Handle the rejected error
});
}).catch(error => {
// Handle the rejected error
});
}).catch(error => {
// Handle the rejected error
});;
این وضعیت را می توان با استفاده از کلمه کلیدی انتظار مدیریت کرد. این باعث می شود کد قابل خواندن تر باشد و ساختار همزمان کد را فراهم می کند.
try {
const data = await getData();
const result = await processData(data);
await displayResult(result);
}catch(error) {
// log error
}
2. ردهای کنترل نشده
مشکل دیگر وعدهها این است که اگر خطایی رخ دهد و وجود نداشته باشد، میتوانند منجر به ردهای غیرقابل کنترل شوند. .catch()
روشی برای رسیدگی به آن وجود دارد.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Something went wrong!'));
}, 1000);
});
promise.then(
(result) => {
console.log(result);
}
);
در این مثال، قول با یک خطا پس از یک ثانیه تاخیر رد می شود. چون وجود ندارد .catch()
روشی که برای رسیدگی به خطا وجود دارد، منجر به رد بدون کنترل می شود.
3. وعده های خیلی زیاد
در نهایت، یکی دیگر از مشکلات مربوط به وعده ها این است که اگر وعده های بیش از حد به طور همزمان ایجاد شود، می توانند منجر به “بیش از حد وعده” شوند. این می تواند منجر به مشکلات عملکرد و نشت حافظه شود.
برای جلوگیری از این مشکل، استفاده از تکنیک هایی مانند throttling و debouncing برای کنترل نرخ ایجاد وعده ها مهم است.
نتیجه
Promises یک ابزار قدرتمند برای برنامه نویسی ناهمزمان در جاوا اسکریپت است و درک نحوه کار آنها برای هر توسعه دهنده وب ضروری است. با استفاده صحیح از وعدهها، میتوانید کدهای کارآمدتر و قابل نگهداریتری بنویسید، در حالی که از دامهای رایجی مانند جهنم پاسخ به تماس و ردهای غیرقابل کنترل جلوگیری کنید.