چگونه وعده های جاوا اسکریپت کار می کند – کتابچه راهنمای مبتدیان
بسیاری از عملیات، مانند درخواست های شبکه، ماهیت ناهمزمان دارند. یکی از مفیدترین و قدرتمندترین ابزارها برای کار با کدهای ناهمزمان Promise است. در این کتاب راهنما، همه چیز را در مورد وعده های جاوا اسکریپت و نحوه استفاده از آنها خواهید آموخت.
فهرست مطالب
مقایسه Promises با سایر الگوهای Async
چگونه نتیجه یک قول را بدست آوریم
نحوه رسیدگی به خطاها با then
چگونه می توان وعده های فوری انجام شده یا رد شده را ایجاد کرد
نحوه استفاده از async
و await
وعده چیست؟
بیایید با نگاهی به اینکه وعده چیست شروع کنیم.
به زبان ساده، Promise یک شی است که یک عملیات ناهمزمان را نشان می دهد. این شی می تواند به شما بگوید چه زمانی عملیات موفقیت آمیز است یا چه زمانی شکست می خورد.
وقتی یک API مبتنی بر Promise را فراخوانی می کنید، تابع یک شی Promise را برمی گرداند که در نهایت نتیجه عملیات را ارائه می دهد.
کشورهای قول
در طول عمر خود، یک Promise می تواند در یکی از سه حالت باشد:
در حال تعلیق : در حالی که عملیات هنوز در حال انجام است، یک وعده در انتظار است. در حالت بیکار است و منتظر نتیجه نهایی (یا خطا) است.
انجام شد : وظیفه ناهمزمانی که Promise را برگرداند با موفقیت انجام شد. یک وعده با مقداری که نتیجه عملیات است محقق می شود.
Rejected : اگر عملیات ناهمزمان با شکست مواجه شد، گفته می شود که Promise رد می شود. یک قول با دلیل رد می شود. این معمولاً یک شی Error
است، اما یک Promise را می توان با هر مقداری رد کرد - حتی یک عدد یا رشته ساده!
یک Promise در حالت معلق شروع می شود، سپس بسته به نتیجه، به حالت انجام شده یا رد شده منتقل می شود. گفته می شود که یک وعده پس از رسیدن به حالت تحقق یافته یا رد شده، حل و فصل می شود.
البته، هیچ تضمینی وجود ندارد که کار ناهمزمان هرگز کامل شود. کاملاً ممکن است که یک Promise
برای همیشه در حالت معلق باقی بماند، اگرچه این به دلیل وجود اشکال در کد کار ناهمزمان است.
مقایسه Promises با سایر الگوهای Async
Promises کمی متفاوت از سایر الگوهای ناهمزمان در جاوا اسکریپت عمل می کند. قبل از غواصی عمیق تر در Promises، اجازه دهید به طور خلاصه Promises را با این تکنیک های دیگر مقایسه کنیم.
توابع پاسخ به تماس
تابع فراخوانی تابعی است که به تابع دیگری منتقل می کنید. هنگامی که تابعی که فراخوانی می کنید کار خود را به پایان رساند، تابع پاسخ به تماس شما را با نتیجه اجرا می کند.
تابعی به نام getUsers
را تصور کنید که یک درخواست شبکه برای دریافت آرایه ای از کاربران می دهد. میتوانید یک تابع callback به getUsers
ارسال کنید، که پس از تکمیل درخواست شبکه، با آرایهای از کاربران فراخوانی میشود:
ابتدا کد بالا "آماده سازی برای دریافت کاربران" را چاپ می کند. سپس getUsers
را فراخوانی می کند که درخواست شبکه را آغاز می کند. اما جاوا اسکریپت منتظر تکمیل درخواست نمی ماند. در عوض، بلافاصله دستور بعدی console.log
را اجرا می کند.
بعداً، پس از بارگیری کاربران، پاسخ تماس شما اجرا میشود و «کاربران دریافت شده» چاپ میشود.
برخی از APIهای مبتنی بر تماس، مانند بسیاری از APIهای Node.js، از تماسهای اول خطا استفاده میکنند. این توابع فراخوانی دو آرگومان می گیرند. آرگومان اول یک خطا است و دومی نتیجه.
به طور معمول، بسته به نتیجه عملیات، تنها یکی از اینها دارای ارزش است. این شبیه به حالات وعده محقق شده و رد شده است.
مشکل با callback API ها در تودرتو است. اگر نیاز به برقراری چند تماس ناهمزمان به صورت متوالی داشته باشید، در نهایت با فراخوانیها و تماسهای تودرتو با عملکرد مواجه خواهید شد.
تصور کنید می خواهید یک فایل را بخوانید، برخی از داده های آن فایل را پردازش کنید، سپس یک فایل جدید بنویسید. هر سه این وظایف ناهمزمان هستند و از یک API مبتنی بر پاسخ به تماس خیالی استفاده می کنند.
با رسیدگی به خطاها سخت تر می شود. تصور کنید که این توابع از تماسهای اول خطا استفاده میکنند:
توابع Callback معمولاً مستقیماً به عنوان یک مکانیسم ناهمزمان در APIهای مدرن استفاده نمی شوند، اما همانطور که به زودی خواهید دید، آنها پایه و اساس انواع دیگر ابزارهای ناهمزمان مانند Promises هستند.
مناسبت ها
رویداد چیزی است که می توانید به آن گوش دهید و به آن پاسخ دهید. برخی از اشیاء در جاوا اسکریپت ساطع کننده رویداد هستند، به این معنی که می توانید شنوندگان رویداد را روی آنها ثبت کنید.
در DOM، بسیاری از عناصر رابط EventTarget
را پیاده سازی می کنند که متدهای addEventListener
و removeEventListener
را ارائه می دهد.
یک نوع معین از رویداد می تواند بیش از یک بار رخ دهد. برای مثال، میتوانید رویداد کلیک را روی یک دکمه گوش دهید:
هر بار که دکمه کلیک می شود، متن "دکمه کلیک شد!" روی کنسول چاپ خواهد شد.
addEventListener
خود تابع callback را می پذیرد. هر زمان که رویداد رخ می دهد، پاسخ تماس اجرا می شود.
یک شی می تواند چندین نوع رویداد را ساطع کند. یک شیء تصویری را در نظر بگیرید. اگر تصویر در URL مشخص شده با موفقیت بارگیری شود، رویداد load
فعال می شود. اگر خطایی وجود داشته باشد، این رویداد راه اندازی نمی شود و در عوض رویداد error
راه اندازی می شود.
فرض کنید قبل از اینکه شنونده رویداد را اضافه کنید، تصویر بارگیری شده است. شما فکر میکنید چه اتفاقی خواهد افتاد؟ هیچ چی! یکی از اشکالات APIهای مبتنی بر رویداد این است که اگر بعد از یک رویداد شنونده رویداد اضافه کنید، پاسخ تماس شما اجرا نخواهد شد. پس از همه، این منطقی است - وقتی یک شنونده کلیک را به یک دکمه اضافه می کنید، نمی خواهید همه رویدادهای کلیک گذشته را دریافت کنید.
اکنون که تماسها و رویدادها را تحلیل کردیم، بیایید نگاهی دقیقتر به Promises بیندازیم.
چگونه یک وعده ایجاد کنیم
می توانید با استفاده از کلمه کلیدی new
با سازنده Promise
یک Promise ایجاد کنید. سازنده Promise
یک تابع callback می گیرد که دو آرگومان به نام های resolve
و reject
می گیرد. هر یک از این آرگومانها تابعی هستند که توسط Promise ارائه میشوند، که برای انتقال Promise به حالت تحقق یافته یا رد شده استفاده میشوند.
در داخل تماس خود، کار ناهمزمان خود را انجام می دهید. در صورت موفقیت آمیز بودن کار، تابع resolve
را با نتیجه نهایی فراخوانی می کنید. اگر خطایی وجود داشت، تابع reject
را با خطا فراخوانی می کنید.
در اینجا یک مثال از ایجاد یک Promise است که تابع setTimeout
مرورگر را میپیچد:
تابع resolve
به عنوان اولین آرگومان به setTimeout
ارسال می شود. پس از سپری شدن زمان مشخص شده توسط duration
، مرورگر تابع resolve
را فراخوانی می کند که Promise را برآورده می کند.
توجه: در این مثال، تاخیر قبل از فراخوانی تابع resolve
ممکن است بیشتر از مدت زمان ارسال شده به تابع باشد. این به این دلیل است که setTimeout
اجرای آن را در زمان مشخص شده تضمین نمی کند.
مهم است که توجه داشته باشید که اغلب اوقات، در واقع نیازی به ساختن Promise خود با دست ندارید. شما معمولاً با Promises بازگردانده شده توسط سایر APIها کار خواهید کرد.
چگونه نتیجه یک قول را بدست آوریم
ما نحوه ایجاد یک Promise را دیدهایم، اما چگونه میتوان نتیجه عملیات ناهمزمان را به دست آورد؟ برای انجام این کار، then
روی خود شی Promise فراخوانی می کنید. then
یک تابع callback را به عنوان آرگومان خود می گیرد. هنگامی که Promise محقق شد، callback با نتیجه اجرا می شود.
بیایید نمونه ای از این را در عمل ببینیم. تابعی به نام getUsers
را تصور کنید که به طور ناهمزمان فهرست ی از اشیاء کاربر را بارگذاری می کند و یک Promise برمی گرداند. میتوانید با تماس با Promise then
توسط getUsers
بازگردانده شده است، فهرست کاربران را دریافت کنید.
درست مانند رویدادها یا API های مبتنی بر تماس، کد شما بدون انتظار برای نتیجه به اجرای خود ادامه می دهد. مدتی بعد، زمانی که کاربران بارگذاری شدند، پاسخ تماس شما برای اجرا برنامه ریزی می شود.
console.log('Loading users'); getUsers() .then(users => { console.log('Got users:', users); }); console.log('Continuing on');
در مثال بالا ابتدا "Loading users" چاپ می شود. مورد بعدی که چاپ می شود "ادامه در" خواهد بود، زیرا تماس getUsers
همچنان در حال بارگیری کاربران است. بعداً چاپ «کاربران دارم» را میبینید.
نحوه رسیدگی به خطاها با then
ما نحوه استفاده از then
را برای دریافت نتیجه ارائه شده به Promise دیدیم، اما در مورد خطاها چطور؟ اگر نتوانیم فهرست کاربران را بارگیری کنیم چه اتفاقی می افتد؟
تابع then
در واقع یک آرگومان دوم، یک callback دیگر را می گیرد. این کنترل کننده خطا است. اگر Promise رد شود، این callback با مقدار rejection اجرا می شود.
getUsers() .then(users => { console.log('Got users:', users); }, error => { console.error('Failed to load users:', error); });
از آنجایی که یک Promise فقط می تواند انجام شود یا رد شود، اما نه هر دو، تنها یکی از این توابع پاسخ به تماس اجرا می شود.
این مهم است که هنگام کار با Promises همیشه خطاها را کنترل کنید. اگر یک Promise rejection دارید که با خطای فراخوانی کنترل نمیشود، در کنسول خود یک استثنا در مورد رد کردن کنترل نشده دریافت خواهید کرد که میتواند باعث ایجاد مشکلاتی برای کاربران شما در زمان اجرا شود.
وعده زنجیر
اگر بخواهید با چندین Promises به صورت سری کار کنید چه؟ مثال قبلی را در نظر بگیرید که در آن ما برخی از داده ها را از یک فایل بارگذاری کردیم، مقداری پردازش انجام دادیم و نتیجه را در یک فایل جدید نوشتیم. فرض کنید توابع readFile
، processData
و writeFile
از Promises به جای callback استفاده می کنند.
ممکن است چیزی شبیه به این را امتحان کنید:
این عالی به نظر نمی رسد، و ما هنوز مشکل تودرتویی را داریم که با رویکرد callback داشتیم. خوشبختانه راه بهتری وجود دارد. می توانید Promises را در یک توالی صاف به هم زنجیره بزنید.
برای اینکه ببینیم این چگونه کار می کند، بیایید عمیق تر به نحوه کارکرد then
نگاه کنیم. ایده کلیدی این است: متد then
Promise دیگری را برمی گرداند. هر مقداری که از then
تماس خود برگردانید، به ارزش تحقق یافته این وعده جدید تبدیل می شود.
تابع getUsers
را در نظر بگیرید که یک Promise را برمیگرداند که با آرایهای از اشیاء کاربر محقق میشود. فرض کنید then
روی این Promise فراخوانی میکنیم، و در بازگشت، اولین کاربر آرایه ( users[0]
) را برمیگردانیم:
getUsers().then(users => users[0]);
پس ، کل این عبارت منجر به یک Promise جدید می شود که با اولین شی کاربر محقق می شود!
این فرآیند بازگرداندن یک Promise، فراخوانی then
و برگرداندن مقدار دیگری که منجر به Promise دیگری می شود، زنجیره ای نامیده می شود.
بیایید این ایده را گسترش دهیم. چه میشود اگر به جای برگرداندن مقداری از then
، Promise دیگری را برگردانیم؟ دوباره مثال پردازش فایل را در نظر بگیرید، جایی که readFile
و processData
هر دو توابع ناهمزمان هستند که Promises را برمیگردانند:
کنترل کننده then
processData
فراخوانی می کند و Promise حاصل را برمی گرداند. مانند قبل، این یک وعده جدید را برمی گرداند. در این حالت، Promise جدید زمانی محقق می شود که Promise برگردانده شده توسط processData
انجام شود و همان مقدار را به شما می دهد. پس کد در مثال بالا یک Promise را برمیگرداند که با دادههای پردازش شده محقق میشود.
می توانید چندین Promises را یکی پس از دیگری زنجیره بزنید تا زمانی که به مقدار نهایی مورد نیاز خود برسید:
در مثال بالا، کل عبارت منجر به یک Promise می شود که تا زمانی که داده های پردازش شده در یک فایل نوشته نشود، محقق نمی شود. "پردازش انجام شد!" روی کنسول چاپ می شود و سپس وعده نهایی محقق می شود.
رسیدگی به خطا در زنجیرههای Promise
در مثال پردازش فایل ما، یک خطا در هر مرحله از فرآیند ممکن است رخ دهد. با استفاده از روش Promise's catch
می توانید خطای هر مرحله از زنجیره Promise را مدیریت کنید.
اگر یکی از Promises در زنجیره رد شود، تابع callback ارسال شده برای catch
اجرا می شود و بقیه زنجیره رد می شود.
نحوه استفاده finally
ممکن است کدی داشته باشید که بخواهید بدون توجه به نتیجه Promise آن را اجرا کنید. به عنوان مثال، شاید بخواهید یک پایگاه داده یا یک فایل را ببندید.
openDatabase() .then(data => processData(data)) .catch(error => console.error('Error')) .finally(() => closeDatabase());
نحوه استفاده از Promise.all
زنجیرههای Promise به شما امکان میدهند چندین کار را به ترتیب انجام دهید، اما اگر بخواهید چندین کار را همزمان اجرا کنید و منتظر بمانید تا همه آنها کامل شوند، چه؟ روش Promise.all
به شما امکان می دهد این کار را انجام دهید.
Promise.all
آرایه ای از Promises را می گیرد و یک Promise جدید برمی گرداند. این وعده زمانی محقق خواهد شد که تمام وعده های دیگر محقق شود. مقدار تحقق آرایه ای است که حاوی مقادیر تحقق هر Promise در آرایه ورودی است.
فرض کنید یک تابع loadUserProfile
دارید که داده های نمایه کاربر را بارگیری می کند، و یک تابع دیگر loadUserPosts
که پست های کاربر را بارگذاری می کند. هر دو یک شناسه کاربری را به عنوان آرگومان می گیرند. تابع سومی وجود دارد، renderUserPage
، که به نمایه و فهرست پست ها نیاز دارد.
در مورد خطاها چطور؟ اگر هر یک از Promises ارسال شده به Promise.all
با خطا رد شود، Promise حاصل نیز با آن خطا رد می شود. اگر هر یک از وعده های دیگر محقق شود، آن ارزش ها از بین می روند.
نحوه استفاده از Promise.allSettled
روش Promise.allSettled
مشابه Promise.all
کار می کند. تفاوت اصلی این است که Promise ارائه شده توسط Promise.allSettled
هرگز رد نخواهد شد.
در عوض، با آرایهای از اشیاء، که ترتیب آنها با ترتیب Promises در آرایه ورودی مطابقت دارد، تکمیل میشود. هر شی دارای یک ویژگی status
است که بسته به نتیجه، یا "تکمیل شد" یا "رد شد".
اگر status
"تحقق شده" باشد، شیء دارای یک value
مقدار نیز خواهد بود که ارزش تحقق وعده را نشان می دهد. اگر status
"رد شده" باشد، شی در عوض دارای یک ویژگی reason
خواهد بود که همان خطا یا شی دیگری است که Promise با آن رد شده است.
دوباره تابع getUser
را در نظر بگیرید که یک شناسه کاربری را می گیرد و یک Promise را برمی گرداند که با داشتن آن شناسه توسط کاربر محقق می شود. میتوانید Promise.allSettled
برای بارگیری موازی آنها استفاده کنید، و مطمئن شوید که همه کاربرانی که با موفقیت بارگیری شدهاند را دریافت میکنید.
میتوانید یک تابع loadUsers
با هدف کلی ایجاد کنید که با توجه به آرایهای از شناسههای کاربر، کاربران را بهطور موازی بارگیری میکند. این تابع یک Promise را برمیگرداند که با آرایهای از همه کاربرانی که با موفقیت بارگذاری شدهاند انجام میشود.
سپس، فقط می توانید getUsers
با آرایه ای از شناسه های کاربری فراخوانی کنید:
چگونه می توان وعده های فوری انجام شده یا رد شده را ایجاد کرد
گاهی اوقات، ممکن است بخواهید ارزشی را در یک وعده محقق شده بپیچید. به عنوان مثال، ممکن است یک تابع ناهمزمان داشته باشید که یک Promise را برمی گرداند، اما یک مورد پایه وجود دارد که در آن مقدار را از قبل می دانید و نیازی به انجام هیچ کار ناهمزمانی ندارید.
برای این کار می توانید Promise.resolve
با یک مقدار فراخوانی کنید. این یک Promise را برمیگرداند که بلافاصله با مقداری که شما مشخص کردهاید محقق میشود:
این کم و بیش معادل موارد زیر است:
new Promise(resolve => { resolve('hello'); }).then(result => { console.log(result); // also prints "hello" });
برای سازگارتر کردن API خود، میتوانید یک Promise فوراً محقق شده ایجاد کنید و در چنین مواردی آن را برگردانید. به این ترتیب، کدی که تابع شما را فراخوانی میکند، میداند که همیشه انتظار یک Promise را دارد، مهم نیست که چه باشد.
به عنوان مثال، تابع getUsers
را که قبلا تعریف شده بود در نظر بگیرید. اگر آرایه شناسه های کاربر خالی است، می توانید به سادگی یک آرایه خالی را برگردانید زیرا هیچ کاربری بارگیری نمی شود.
کاربرد دیگر Promise.resolve
رسیدگی به مواردی است که در آن مقداری به شما داده می شود که ممکن است Promise باشد یا نباشد، اما می خواهید همیشه با آن به عنوان یک Promise رفتار کنید.
میتوانید با خیال راحت Promise.resolve
با هر مقداری تماس بگیرید. اگر قبلاً یک Promise بود، فقط Promise دیگری دریافت خواهید کرد که همان ارزش تحقق یا رد را دارد. اگر وعده ای نبود، در یک وعده وفای فوری پیچیده می شود.
مزیت این روش این است که نیازی به انجام چنین کاری ندارید:
به طور مشابه، می توانید یک Promise بلافاصله رد شده با Promise.reject
ایجاد کنید. اگر یک بار دیگر به تابع getUsers
برگردیم، شاید بخواهیم اگر آرایه شناسه کاربر null
، undefined
یا آرایه نباشد، فوراً رد کنیم.
نحوه استفاده از Promise.race
درست مانند Promise.all
یا Promise.allSettled
، روش استاتیک Promise.race
آرایه ای از Promises را می گیرد و یک Promise جدید برمی گرداند. همانطور که از نام آن پیداست، اگرچه تا حدودی متفاوت عمل می کند.
وعده ای که توسط Promise.race
برگردانده می شود تا زمانی که اولین وعده از وعده های داده شده محقق شود یا رد شود، صبر می کند و سپس آن وعده نیز با همان مقدار محقق یا رد می شود. هنگامی که این اتفاق می افتد، ارزش های تحقق یافته یا رد شده سایر وعده ها از بین می روند.
نحوه استفاده از Promise.any
Promise.any
مشابه Promise.race
با یک تفاوت کلیدی کار می کند - جایی که Promise.race
به محض تحقق یا رد شدن هر وعده انجام می شود، Promise.any
منتظر اولین وعده انجام شده است.
نحوه استفاده از async
و await
async
و await
کلمات کلیدی خاصی هستند که کار با Promises را ساده می کنند. آنها نیاز به توابع پاسخ به تماس و فراخوانی به then
یا catch
حذف می کنند. آنها با بلوکهای try-catch نیز کار میکنند.
در اینجا نحوه کار آن آمده است. به جای then
یک Promise، با قرار دادن کلمه کلیدی await
قبل از آن، await
آن هستید. این عملاً اجرای تابع را تا زمانی که Promise محقق شود، متوقف می کند.
در اینجا یک مثال با استفاده از Promises استاندارد آورده شده است:
در اینجا کد معادل با استفاده از کلمه کلیدی await
آمده است:
زنجیر وعده نیز کمی تمیزتر است:
به یاد داشته باشید که هر استفاده از await
اجرای بقیه عملکرد را متوقف می کند تا زمانی که وعده ای که در انتظار آن هستید محقق شود. اگر می خواهید منتظر چندین Promise باشید که به صورت موازی اجرا می شوند، می توانید از Promise.all
استفاده کنید:
برای استفاده از کلمه کلیدی await
، تابع شما باید به عنوان یک تابع ناهمگام علامت گذاری شود. می توانید این کار را با قرار دادن کلمه کلیدی async
قبل از تابع خود انجام دهید:
گفت ن کلمه کلیدی async
نیز تأثیر مهم دیگری بر عملکرد دارد. توابع Async همیشه به طور ضمنی یک Promise را برمی گرداند. اگر مقداری را از یک تابع async برگردانید، تابع در واقع یک Promise را برمیگرداند که با آن مقدار محقق شده است.
در مثال بالا، تابع مجموع دو آرگومان a
و b
را برمی گرداند. اما از آنجایی که یک تابع async
است، مجموع را برمیگرداند، بلکه یک Promise است که با مجموع انجام میشود.
رسیدگی به خطا با async
و await
ما از await
استفاده می کنیم تا منتظر باشیم تا Promise محقق شود، اما در مورد رسیدگی به خطاها چطور؟ اگر شما منتظر یک وعده هستید و آن را رد می کنید، یک خطا انجام می شود. این بدان معناست که برای رسیدگی به خطا، می توانید آن را در یک بلوک try-catch قرار دهید:
وعده ضد الگوها
ایجاد بیهوده یک وعده جدید
گاهی اوقات کاری برای ایجاد یک وعده جدید وجود ندارد. اما اگر قبلاً با Promises بازگردانده شده توسط API کار می کنید، معمولاً نیازی به ایجاد Promise خود ندارید:
در این مثال، ما یک Promise جدید برای بسته بندی Fetch API ایجاد می کنیم که قبلاً Promises را برمی گرداند. این غیر ضروری است. در عوض، فقط زنجیره Promise را مستقیماً از Fetch API برگردانید:
در هر دو مورد، کد فراخوانی getUsers
یکسان به نظر می رسد:
خطاهای بلع
این نسخه از تابع getUsers
را در نظر بگیرید:
رسیدگی به خطا خوب است، درست است؟ اگر این تابع getUsers
را صدا کنیم، ممکن است از نتیجه شگفت زده شوید:
ممکن است انتظار داشته باشید که "خطا" چاپ شود، اما در واقع "کاربران دریافت شده: تعریف نشده" را چاپ می کند. این به این دلیل است که catch
call خطا را «بلع» میکند و یک Promise جدید را برمیگرداند که با مقدار بازگشتی catch
back که undefined
است ( console.error
undefined
را برمیگرداند) انجام میشود. شما همچنان پیام گزارش "خطا در بارگیری کاربران" را از getUsers
خواهید دید، اما وعده بازگشتی محقق می شود، رد نمی شود.
اگر میخواهید خطای داخل تابع getUsers
را دریافت کنید و همچنان Promise برگشتی را رد کنید، کنترل کننده catch
باید یک Promise رد شده را برگرداند. می توانید این کار را با استفاده از Promise.reject
انجام دهید.
اکنون همچنان پیام «خطا در بارگیری کاربران» را دریافت خواهید کرد، اما Promise برگشتی نیز با این خطا رد خواهد شد.
وعده های تودرتو
از قرار دادن کد Promise خودداری کنید. در عوض، سعی کنید از زنجیرهای مسطح Promise استفاده کنید.
به جای این:
readFile(sourceFile) .then(data => { processData(data) .then(result => { writeFile(result, outputFile) .then(() => console.log('done'); }); });
readFile(sourceFile) .then(data => processData(data)) .then(result => writeFile(result, outputFile)) .then(() => console.log('done'));
خلاصه
در اینجا نکات کلیدی برای کار با Promises وجود دارد:
یک قول می تواند در حال تعلیق باشد، محقق شود یا رد شود
یک وعده در صورت تحقق یا رد شدن، حل می شود
then
از آن برای بدست آوردن ارزش برآورده شده یک Promise استفاده کنید
از catch
برای رسیدگی به خطاها استفاده کنید
finally
برای اجرای منطق پاکسازی که در صورت موفقیت یا خطا به آن نیاز دارید، استفاده کنید
زنجیره ای با هم قول می دهد که وظایف ناهمزمان را به ترتیب انجام دهند
از Promise.all
برای دریافت قولی استفاده کنید که در صورت تحقق همه وعدههای داده شده محقق میشود، یا زمانی که یکی از آن وعدهها رد میشود، رد میشود.
Promise.allSettled
برای دریافت قولی استفاده کنید که زمانی محقق می شود که همه وعده های داده شده محقق شوند یا رد شوند.
Promise.race
برای دریافت قولی استفاده کنید که در صورت تحقق یا رد شدن اولین وعده داده شده محقق یا رد شود.
از Promise.any
برای دریافت وعده ای استفاده کنید که با تحقق اولین وعده از وعده های داده شده محقق شود.
از کلمه کلیدی await
برای منتظر ماندن برای ارزش تحقق یک Promise استفاده کنید
هنگام استفاده از کلمه کلیدی await
از یک بلوک try-catch برای رسیدگی به خطاها استفاده کنید
تابعی که از await
در داخل آن استفاده می کند باید از کلمه کلیدی async
استفاده کند
از شما برای خواندن این شیرجه عمیق در Promises متشکریم. امیدوارم چیز جدیدی یاد گرفته باشید!
ارسال نظر