تابعهای Overload شده به توابعی گفته میشود که نامی یکسان اما آرگومان(های) متفاوتی دارند. در این مقاله به بررسی نمونههایی از تابعهای Overload شده میپردازیم. برای مطالعه بخش قبلی این مجموعه مقالات آموزشی به لینک زیر مراجعه کنید:
چنان که در بخشهای قبلی صحبت کردیم تابع به معنی قطعه کدی است که به گروهبندی کد میپردازد و وظیفه خاصی را اجرا میکند. در برنامهنویسی ++C دو تابع به شرط این که تعداد و/یا نوع آرگومانهایی که ارسال میشوند متفاوت باشند، میتوانند نام یکسانی داشته باشند.
در تابعهای زیر نوع یا تعداد (و یا هر دوی) پارامترها متفاوت هستند و لذا به نام تابعهای overload شده شناخته میشوند:
در قطعه کد فوق 4 تابع به صورت تابعهای overload شده هستند، زیرا آرگومان(های) ارسالی به این تابعها متفاوت هستند. توجه داشته باشید که نوع بازگشتی هر 4 تابع یکسان هستند. تابعهای overload شده ممکن است نوع بازگشتی متفاوتی داشته باشند یا نداشته باشند، اما حتماً باید آرگومانهای متفاوتی داشته باشند.
تعداد و نوع آرگومانهای ارسالی به این دو تابع حتی با این که نوع بازگشتی متفاوت است، یکسان هستند. از این رو کامپایلر خطایی ایجاد میکند.
overload کردن تابع:
Integer number: 5 Float number: 5.5 Integer number: 5 and float number: 5.5
در کد فوق، تابع ()display سه بار با انواع یا تعداد متفاوتی از آرگومانها فراخوانی میشود. نوع بازگشتی همه این تابعها یکسان است، اما الزامی برای این مسئله وجود ندارد.
overload کردن تابع:
Absolute value of -5 = 5 Absolute value of 5.5 = 5.5
در مثال فوق، دو تابع ()absolute به صورت overload شده هستند. هر دو تابع آرگومان منفردی میگیرند. با این حال، یک تابع مقدار integer به عنوان آرگومان میگیرد و آرگومان دیگر از نوع float است. زمانی که تابع ()absolute با یک آرگومان integer فراخوانی شود، این تابع فراخوانی میشود:
اما زمانی که تابع ()absolute با یک آرگومان float فراخوانی شود، تابع زیر فراخوانی میشود:
بدین ترتیب به پایان این بخش از سری مقالات آموزش زبان برنامهنویسی ++C میرسیم.
ماژول http در Node.js تابعها و کلاس مفیدی برای ساختن سرور HTTP ارائه میکند. در واقع یک ماژول کلیدی Node.js برای شبکه محسوب میشود. در این نوشته به بررسی کارکردهای مختلف این ماژول میپردازیم. برای مطالعه بخش قبلی این مجموعه مقالات آموزشی به لینک زیر رجوع کنید:
شما میتوانید با استفاده از دستور زیر این ماژول را در فایل خود include کنید:
ماژول مورد اشاره برخی مشخصهها و متدها و همچنین برخی کلاسها را ارائه میکند.
در این بخش به بررسی مشخصههای ماژول http میپردازیم.
این مشخصه لیستی از همه متدهای مورد پشتیبانی HTTP را ارائه میکند:
این مشخصه همه کدهای حالت HTTP و توصیف آنها را لیست میکند:
این مشخصه به وهلهای سراسری از شیء Agent اشاره میکند که وهلهای از کلاس http.Agent است. این مشخصه به مدیریت اتصالهای دائمی میپردازد و از آنها برای کلاینتهای HTTP استفاده مجدد میکند و مؤلفهای کلیدی برای شبکهبندی HTTP در Node.js محسوب میشود. برای مشاهده توضیحات بیشتر در خصوص http.Agent به ادامه همین مقاله مراجعه کنید.
در این بخش متدهای موجود در ماژول http را معرفی میکنیم.
این متد یک وهله از کلاس http.Server بازگشت میدهد. کاربرد آن به صورت زیر است:
یک درخواست HTTP به سرور ایجاد میکند و وهلهای از کلاس http.ClientRequest میسازد.
مشابه ()http.request است، اما به صورت خودکار متد HTTP را روی GET تنظیم میکند و ()req.end را به صورت خودکار فراخوانی میکند.
ماژول HTTP پنج کلاس ارائه میکند که در ادامه به آنها میپردازیم:
Node وهلهای سراسری از کلاس http.Agent برای مدیریت تداوم اتصال و استفاده مجدد از کلاینتهای HTTP ارائه میکند که مؤلفهای کلیدی برای شبکهبندی HTTP محسوب میشود. بدین ترتیب مطمئن میشویم که هر درخواست که به سرور ارسال میشود صفبندی شده و یک سوکت منفرد مورد استفاده مجدد قرار میگیرد. همچنین یک استخر از سوکتها نگهداری میکند که برای حفظ عملکرد مؤلفهای کلیدی محسوب میشود.
هر شیء http.ClientRequest زمانی که ()http.request یا ()http.get فراخوانی میشود، ایجاد خواهد شد. زمانی که پاسخی دریافت میشود، رویداد response با استفاده از پاسخ فراخوانی میشود و آرگومان آن نیز وهلهای از http.IncomingMessage است.
در مورد دادههای بازگشتی یک پاسخ را میتوان به 2 روش خواند:
این کلاس به طور معمول زمانی وهلهسازی و بازگشت داده میشود که یک سرور جدید با استفاده از ()http.createServer ساخته میشود.
زمانی که یک شیء سرور دارید، به متدهای آن نیز دسترسی دارید:
این کلاس به وسیله http.Server ساخته شده است و به عنوان پارامتر دوم به رویداد request ارسال میشود. این کلاس به طور معمول در کد به صورت res نوشته و استفاده میشود:
متدی که معمولاً در دستگیره فراخوانی میشود ()end نام دارد که موجب بسته شدن response میشود و بدین ترتیب با کامل شدن پیام، سرور میتواند آن را به کلاینت بفرستد. آن را باید روی هر پاسخ فراخوانی کرد.
از این متدها برای تعامل با هدرهای HTTP استفاده میشود:
پس از پردازش هدرها میتوان آنها را مستقیماً با فراخوانی ()response.writeHead به کلاینت ارسال کرد. این متد یک statusCode به عنوان پارامتر اول میگیرد و پیام وضعیت و شیء هدر نیز اختیاری هستند.
برای ارسال دادهها به کلاینت در بدنه پاسخ باید از متد ()write استفاده کنید. این متد دادههای بافر شده را به استریم پاسخ HTTP میفرستد.
اگر هدرها با استفاده از ()response.writeHead ارسال نشده باشند، ابتدا به همراه کد وضعیت و پیام آن که در درخواست تنظیم شده فرستاده میشوند. این موارد را میتوانید با تنظیم مقادیر مشخصههای statusCode و statusMessage تغییر دهید.
یک شیء http.IncomingMessage به صورت زیر ساخته میشود:
از این کلاس میتوان برای دسترسی به اجزای پاسخ به صورت زیر استفاده کرد:
این دادهها با استفاده از استریمها در دسترس ما قرار میگیرند، زیرا http.IncomingMessage اینترفیس Readable Stream را پیادهسازی میکند.
بدین ترتیب به پایان این بخش از سری مقالات آموزش Node.js میرسیم.
اگر
منبع: فرادرس
تصور کنید ایدهای عالی برای ساخت یک اپلیکیشن برای گوشیهای هوشمند دارید و میخواهید بدانید که چگونه باید شروع به این کار بکنید؟ در این مقاله با شیوه ساخت یک اپلیکیشن و تبدیل ایده به محصول نهایی آشنا میشوید، به طوری که افراد مختلف میتوانند اپلیکیشن شما را از اپاستور اپل یا پلیاستور گوگل دانلود کنند. در ادامه با مراحل طراحی یک اپلیکیشن آشنا خواهیم شد.
در این نوشته با اهمیت ضروری تحقیق آشنا میشویم و این نکته را روشن میسازیم که چرا باید در مورد مفهوم اپلیکیشن خود شور و اشتیاق داشته باشید. همچنین به شما کمک میکنیم که مهارتهای مختلف مورد نیاز برای موفقیت را بیاموزید و مفاهیم ارزشمندی که میتوانید برای ساخت تجربه کاربری اپلیکیشنتان مورد استفاده قرار دهید را میشناسیم.
اغلب افراد در نخستین گام وسوسه میشوند که مستقیماً شروع به تفکر در مورد روش ساخت اپلیکیشن بکنند، اما همواره باید مسیر توسعه اپلیکیشن را با به دست آوردن ایدهای روشن از هدف خود آغاز کنید. برای این که بدانید معنی این حرف چیست، باید در مورد کاری که اپلیکیشنتان انجام میدهد، ایده روشنی داشته باشید، همچنین بدانید که کاربران اپلیکیشن شما چه کسانی هستند و به چه صورت از اپلیکیشن شما استفاده خواهند کرد. بدین ترتیب باید این سؤالها را از خودتان بپرسید:
این نوع از تحقیق به معنی صحبت کردن با افراد مختلف و بررسی نظرات آنها در مورد ایده اپلیکیشن است. گرچه این کار ممکن است ملالآور به نظر برسد، اما لازم نیست نگران باشید، چون شما یک شرکت بزرگ نیستید که نیاز به مصاحبه با هزاران نفر داشته باشید، صحبت کردن با دوستان، خانواده، همکاران، و یا همکلاسها نیز در این خصوص به قدر کافی مفید است.
همچنین باید در مورد اپلیکیشنهایی که اپ شما با آنها رقابت خواهد کرد نیز تحقیق کنید. کاوش پلیاستور یا اپاستور برای یافتن اپلیکیشنهایی که کاری مشابه ایده محصول شما انجام میدهند به این منظور مفید خواهد بود. این اپلیکیشنها را روی گوشی خود دانلود کنید تا بتوانید کاری که اجرا میکنند را تحلیل کرده و قابلیتهایی که ارائه میدهند را مورد بررسی قرار دهید. از خود بپرسید آیا اپلیکیشنهای مربوطه وظایفی که در نظر دارند را با موفقیت اجرا میکنند و اگر چنین است ایده آنها با مفهومی که شما در ذهن خود دارید چه نسبتی دارد؟ درک اپلیکیشنهای رقیب به شما کمک میکند که ارزشهای خاص اپلیکیشن خود را درک کنید. بدین ترتیب میتوانید در صورت نیاز ایدههای خود را طوری اصلاح کنید که کاربران، خدماتی که شما ارائه میکنید را جای دیگری نتوانند پیدا کنند.
نکته مهم: اگر نمیخواهید منحصربهفرد باشید، در این صورت باید بهتر از رقبا باشید.
هر زمان که از یک اپلیکیشن محبوب خود استفاده میکنید، تلاش کنید با دیدی تحلیلی به بررسی آن چه موجب جذب شما به آن شده است نگاه کنید. آیا محتوای آن به خوبی سازماندهی یافته است؟ آیا طراحی آن روی گوشی شما عالی به نظر میرسد. آیا از سرعت کارکرد آن تحت تأثیر قرار میگیرید؟ با چند ضربه روی صفحه گوشی میتوانید هدف مورد نظر خود را اجرا کنید؟ آیا امکاناتی وجود دارند که هرگز استفاده نکردهاید؟ آیا فکر میکنید طراحی آن تکیه زیادی روی متن دارد؟ چنین تفکرهای نقادانهای میتواند به ایجاد درکی از شیوه ایجاد تجربه کاربری اپلیکیشن خودتان کمک کند.
بسیار مهم است در مورد پروژهای که برای ساخت انتخاب میکنید از آغاز اشتیاق داشته باشید. نخستین اپلیکیشن شما نیاز به تعهد کاری بالا دارد و این که انرژی شما در طول پروژه نوسان داشته باشد، کاملاً طبیعی است اما کار کردن روی چیزی که در مورد آن اشتیاق دارید موجب خواهد شد که متمرکز بمانید و برای به پایان رساندن پروژه انگیزه کافی داشته باشید.

همه کارهای مفهومی که تا به اینجا صحبت کردیم برای موفقیت یک محصول کاملاً ضروری هستند، اما اینها تنها بخشی از چالش هستند. شما باید دانش فنی مناسبی نیز برای حیات بخشیدن به ایده خود داشته باشید. بسته به مهارتها و تجربه فعلیتان ممکن است لازم باشد پیش از آغاز عملی کار ساخت اپلیکیشن نیاز به آموختن مواردی داشته باشید. فرادرس بازه گستردهای از دورههای آموزش ویدئویی و مجموعه مقالات متنی برای آموزش شما ارائه کرده است. برای نمونه میتوانید از آموزشهای زیر برای کسب مهارت مورد نیاز جهت توسعه اپلیکیشن خودتان کمک بگیرید:
از جمله آموزشهایی هستند که میتوانید برای ساخت اپلیکیشن برای پلتفرمهای مختلف مورد استفاده قرار دهید. شما با مطالعه این آموزشها میتوانید با مهارتهای اساسی مورد نیاز برای ساخت اپلیکیشن آشنا شوید و همچنین احیاناً مهارتهایی که برای ساخت اپلیکیشن برای محیط اندروید و iOS ندارید را بشناسید.
یک رویکرد مفید که میتوان برای توسعه مهارتهای برنامهنویسی مورد استفاده قرار دارد، این است که مجموعه مهارتهای خود را مورد بررسی قرار دهید و مهارتهای جدیدی که باید یاد بگیرید را شناسایی کنید. به این منظور یک کاغذ بردارید و دو ستون روی آن رسم کنید. در ستون اول همه مهارتهای کنونی خود را لیست کنید. در ستون دوم همه مهارتهایی را بنویسید که فکر میکنید باید برای رسیدن به هدف کسب کنید. این مهارتها بر مبنای آن چه که تاکنون از توسعه اپلیکیشن آموختهاید، قابل شناسایی خواهند بود. زمانی که این کار را انجام دادید، مهارتهای مشترک دو ستون را خط بزنید و آنچه باقی میماند مهارتهایی هستند که برای تبدیل ایده اپلیکیشن به واقعیت باید بیاموزید. زمانی که مهارتهای مورد نیاز برای یادگیری را شناسایی کردید، تنها گام بعدی این است که مسیر یادگیری صحیحی را انتخاب کنید.
واقعگرایی در مورد مهارتهای کنونی بسیار حائز اهمیت است، چون این که کدام تجربه یادگیری برای شما مؤثرتر است و کدام چارچوب زمانی را برای توسعه اپلیکیشن خود در نظر دارید میتواند تفاوت مهمی ایجاد کند.
زمانی که از مهارتهای جدید و تحقیقات میدانی برای خلق اپلیکیشن خود استفاده میکنید، باید همواره به خاطر داشته باشید که طراحی نهایی باید در حد امکان ساده و متمرکز باشد. تحقیق شما باید عواملی که کاربران شما مهمتر میپندارند را مشخص سازد. برای نمونه اگر یک مشکل اساسی وجود دارد که کاربران انتظار دارند اپلیکیشن شما حل کند، باید صرفاً روی آن مسئله متمرکز شوید. اگر کاربران بر این باورند که یک عنصر از بازی سرگرمکنندهتر است، کانون توجه خود را روی آن متمرکز کنید. این رویکرد بدان معنی است که از صرف زمان ارزشمند توسعه روی قابلیتهایی که برای کاربران اهمیت ندارد اجتناب میکنید.
توسعه اپلیکیشن در مراحل اولیه میتواند آزمونی واقعی از میزان تعهد، صبر و تواناییهای شما باشد، بنابراین ایده جستجوی پشتیبانی برای این که متمرکز باشید و از مسیر خارج نشوید بسیار مهم است. اگر امکان دارید بهتر است از کمکهای یک مربی کمک بگیرید که شما را راهنمایی و هدایت کند. فورورمهای برنامهنویسی نیز منبع جالبی از توصیههای برنامه نویسان دیگر هستند که در زمان مواجهه با مشکلهای مشابه یا نیاز به ایدههای جدید بیشتر در حوزههای مختلف به کار میآیند.
مربیها و همتایان این نکته را به شما یادآوری میکنند که فرایند ساخت اپلیکیشن یک تجربه یادگیری است. حتی در مراحل مقدماتی ممکن است به سادگی درگیر جزییات گیجکننده توسعه اپلیکیشن شوید. بنابراین اگر حتی به چالشبرانگیزترین لحظههای کار به عنوان بخشی از مسیر توسعه خود بنگرید، بسیار به حفظ انگیزه شما کمک میکند.

اکنون زمان آن رسیده که دانش خود را به صورت عملی مورد استفاده قرار دهید؛ به زبان سادهتر، حالا شما ابزارهای لازم برای تبدیل ایده خود به یک اپلیکیشن تلفنهای هوشمند را در اختیار دارید. با در ذهن داشتن ایدهای که در مورد آن مشتاق هستید، پیادهسازی یک طراحی مناسب برای این ایده بر مبنای تحقیق از کاربران و در کنار هم قرار دادن مهارتهای صحیح به یقین هیچکس بهتر از شما نمیتواند اپلیکیشنی که در ذهن خود به آن فکر میکنید را توسعه دهد. همین امروز شروع کنید تا در آیندهای نزدیک همگان را شگفتزده کنید.
جاوا اسکریپت به صورت پیشفرض یک زبان برنامهنویسی همگام و تک نخی است. این بدان معنی است که کد نمیتواند نخهای جدیدی ایجاد کرده و به صورت موازی اجرا شود. در این مقاله به بررسی روشهای مختلف برنامه نویسی ناهمگام در محیط Node.js میپردازیم. برای مطالعه بخش قبلی این سری مقالات به لینک زیر رجوع کنید:
رایانهها اساساً دارای طراحی ناهمگام هستند. منظور از ناهمگامی این است که کارهای مختلف میتوانند در گردش برنامه اصلی مستقل از هم اتفاق بیفتند. در رایانههای امروز هر برنامهای برای مدت زمان معینی اجرا میشود و سپس اجرای آن متوقف میشود تا برنامه دیگری بتواند به اجرای خود ادامه بدهد. این کار در چنان چرخه سریعی اتفاق میافتد که کاربر هرگز متوجه نمیشود و ما فکر میکنیم رایانه ما میتواند به طور همزمان برنامههای زیادی را اجرا کند، اما این یک توهم است (البته قضیه در پردازندههای چندهستهای متفاوت است).
برنامهها به صورت داخلی از «وقفه» (interrupt) استفاده میکنند. وقفه یک سیگنال است که به سمت پردازنده ارسال میشود تا توجه سیستم را کسب کند. پرداختن به جزییات این موضوع خارج از موضوع این مقاله است؛ اما باید به خاطر داشته باشید که ناهمگامی در برنامهها امری معمول است و به طور نرمال برنامهها، اجرای خود را متوقف میکنند تا زمانی که پردازنده به آنها وقتی اختصاص بدهد. زمانی که یک برنامه منتظر پاسخی از سوی شبکه است، نمیتواند پردازنده را معطل خود نگه دارد تا درخواست پایان یابد.
به طور معمول زبانهای برنامهنویسی همگام هستند. برخی از آنها نیز در حد زبان یا کتابخانههای جانبی، روشهایی برای مدیریت ناهمگامی ارائه میکنند. زبانهای C ،Java ،C# ،PHP ،Go ،Ruby ،Swift و Python همگی به صورت پیشفرض همگام هستند. برخی از این زبانها با استفاده از نخها به صورت ناهمگام عمل میکنند و میتوانند یک پردازش جدید ایجاد کنند.
زبان برنامهنویسی جاوا اسکریپت نیز به صورت پیشفرض همگام و تک نخی است. این بدان معنی است که کد نمیتواند نخهای جدید ایجاد کرده و به صورت موازی اجرا شود. در این حالت، خطوط مختلف کد یکی پس از دیگری و به ترتیب اجرا میشوند. برای نمونه:
اما میدانیم که جاوا اسکریپت درون مرورگر تولد یافته است و وظیفه اصلی آن در ابتدا پاسخ دادن به واکنشهای کاربر مانند onClick ،onMouseOver ،onChange ،onSubmit و غیره بوده است. چنین فرایندی در یک مدل برنامهنویسی همگام چگونه ممکن است؟
پاسخ در محیط برنامهنویسی این زبان است. مرورگر روشی برای ارائه یک مجموعه از API-ها دارد که میتوانند این نوع کارکرد را مدیریت کنند. در سالهای اخیر Node.js یک محیط غیر مسدودکننده I/O معرفی کرده است که این مفهوم را به دسترسی فایلها، فراخوانیهای شبکه و موارد مشابه گسترش داده است.
ما هرگز نمیدانیم که یک کاربر چه زمانی روی یک دکمه کلیک خواهد کرد، بنابراین باید یک «دستگیره رویداد» (event handler) برای رویداد کلیک تعریف کنیم.
این دستگیره رویداد تابعی قبول میکند که هنگام اتفاق افتادن رویداد فراخوانی میشود:
این همان callback مشهور است. در واقع callback تابع سادهای است که به صورت یک مقدار به تابع دیگر ارسال میشوند و تنها زمانی اجرا خواهد شد که رویدادی اتفاق بیفتد. ما این کار را به این دلیل میتوانیم اجرا کنیم که جاوا اسکریپت تابعهای درجه نخست دارد که میتوانند به متغیرها انتساب یافته و به تابعهای دیگر (که تابعهای درجه بالا نامیده میشوند) ارسال شوند.
رویه معمول این است که کد کلاینت در یک شنونده رویداد load در شیء window قرار میگیرد و تابع callback را در زمان آماده شدن صفحه اجرا میکند:
Callback-ها در همه جا استفاده میشوند و اختصاص به رویدادهای DOM ندارند. یک مثال عمومی استفاده از تایمر است:
درخواستهای XHR نیز یک callback میپذیرند. در مثال زیر یک تابع به مشخصهای که در زمان رخداد اتفاق خاص فراخوانی میشود، انتساب خواهد یافت:
یکی از رایجترین راهبردها برای مدیریت خطا در callback-ها کاری است که Node.js انجام میدهد. پارامتر اول در هر تابع callback شیء خطا است که به نام callback-های error-first شناخته میشوند.
اگر خطایی وجود نداشته باشد، این شیء null خواهد بود. اگر خطایی رخ داده باشد این پارامتر نوعی توضیح در مورد خطا و اطلاعات مرتبط ارائه میکند.
Callback-ها در استفادههای ساده بسیار عالی هستند. اما هر Callback یک سطح به سلسلهمراتب تودرتو اضافه میکند. زمانی که Callback-های زیادی وجود داشته باشند، کد به سرعت پیچیده میشود:
این کد صرفاً 4 سطح ساده دارد، اما در موارد زیادی سطوح بسیار بیشتری از کد تودرتو را مشاهده میکنیم که جالب نیست. برای حل این مشکل چه باید کرد؟
از ES6 به بعد جاوا اسکریپت چند قابلیت معرفی کرده است که به کدنویسی ناهمگام بدون استفاده از Callback-ها کمک میکند:
Promise-ها یک روش برای اجرای کد ناهمگام در جاوا اسکریپت محسوب میشوند و با استفاده از آنها دیگر لازم نیست نگران وجود Callback-های زیاد در کد باشیم.
یک Promise عموماً به صورت واسطی برای یک مقدار تعریف میشود که در زمانی در آینده موجود خواهد شد. با این که سالهاست Promise-ها معرفی شدهاند اما صرفاً در ES2015 استاندارد و معرفی شدند و هم اکنون در ES2017 با معرفی تابعهای async منسوخ گشتهاند. تابعهای async از API مربوط به Promise ها به عنوان بلوکهای سازنده خود استفاده میکند و از این رو درک آنها حتی در صورتی که بخواهید در کد خود از تابعهای async به جای promise استفاده کنید ضروری خواهد بود.
زمانی که یک Promise فراخوانی میشود در «حالت انتظار» (pending state) کار خود را آغاز میکند. این بدان معنی است که تابع فراخواننده به اجرای خود ادامه میدهد در حالی که منتظر Promise است تا پردازشهای خودش را اجرا کند و بازخوردی به تابع فراخواننده بدهد.
در این زمان تابع فراخواننده منتظر آن میماند تا Promise را در «حالت حل شده» (resolved state) یا در «حالت رد شده» (rejected state) بازگشت دهد، اما چنان که میدانید جاوا اسکریپت همگام است و از این رو در زمانی که Promise کار نمیکند، تابع همچنان به اجرای خود ادامه میدهد.
علاوه بر کد کاربر و کد کتابخانههای مختلف، Promise-ها از سوی API-های مدرن استاندارد وب مانند لیست زیر نیز مورد استفاده قرار میگیرند:
این که در جاوا اسکریپت مدرن از Promise-ها استفاده نکنید امر بسیار نامحتملی است، بنابراین در ادامه به بررسی دقیقتر آنها میپردازیم.
API مربوط به Promise یک سازنده Promise عرضه میکند که با استفاده از ()new Promise مقداردهی اولیه میشود:
چنان که میبینید Promise ثابت سراسری done را بررسی میکند و اگر درست باشد، یک Promise حل شده و در غیر این صورت Promise رد شده بازگشت مییابد. ما با استفاده از resolve و reject میتوانیم یک مقدار را بازگشت دهیم. در حالت فوق ما صرفاً یک رشته بازگشت میدهیم اما میتوان یک شیء را نیز بازگشت داد.
در بخش قبلی، با روش ایجاد شدن یک Promise آشنا شدیم. اکنون به بررسی شیوه مصرف یا استفاده شدن یک Promise میپردازیم:
اجرای ()checkIfItsDone موجب اجرا شدن یک Promise به نام ()isItDoneYet میشود که منتظر حل شدن با استفاده از Callback-ی به نام then باقی میماند و اگر خطایی رخ دهد آن را در callback با نام catch مدیریت میکند.
هر Promise میتواند به Promise دیگری بازگشت یابد و یک زنجیره از Promise-ها تشکیل دهد. مثالی عالی از زنجیرهسازی Promise-ها در API با نام Fetch مشاهده میشود که یک لایه فوقانی روی API مربوط به XMLHttpRequest است و میتوان از آن برای ایجاد یک منبع و صفبندی یک زنجیره از Promise-ها برای اجرا در زمان واکشی شدن منبع استفاده کرد.
API با نام Fetch یک سازوکار مبتنی بر Promise است به طوری که فراخوانی ()fetch معادل تعریف کردن یک Promise با استفاده از ()new Promise است.
اجرای ()fetch موجب بازگشت یک response میشود که مشخصههای زیادی دارد، اما دو مورد از آنها برای ما مهم هستند:
response یک متد ()json نیز دارد که یک Promise بازگشت میدهد و در آن به بررسی محتوای متنی پردازش شده و تبدیل آن به JSON میپردازد. با توجه به Promise-های فوق روند رویدادها به این صورت است که Promise اول در زنجیره، تابعی است که ما تعریف کردهایم و آن را ()status مینامیم. این Promise وضعیت پاسخ را بررسی میکند و در صورتی که پاسخ موفق (کد بین 200 تا 299) نباشد، Promise را رد میکند.
این عملیات موجب میشود که زنجیره Promise همه Promise-های بعدی لیست شده را رد کند و مستقیماً به گزاره ()catch در انتهای کد برسد و متن Request failed را به همراه پیام خطا لاگ کند. اما اگر Promise اول موفق باشد، تابع ()json را که تعریف کردهایم، فراخوانی میکند. از آنجا که Promise قبلی در صورت موفقیت، شیء response را بازگشت داده است، میتوانیم آن را به عنوان ورودی به Promise دوم بدهیم.
در این حالت، دادههای JSON پردازش شده را بازگشت میدهیم تا Promise سوم مستقیماً JSON را دریافت کند:
در نهایت آن را در کنسول لاگ میکنیم.
در مثال بخش قبلی، یک catch داشتیم که به زنجیره Promise-ها الصاق میشد. هر زمان که جزئی از زنجیره Promise-ها ناموفق باشد و خطایی رخ دهد یا یک Promise رد شود، کنترل به گزاره ()catch در انتهای زنجیره میرسد.
یا
اگر درون ()catch خطایی رخ دهد، میتوان یک ()catch دیگر برای مدیریت آن الصاق کرد و این روند همین طور تا انتها ادامه مییابد:
در این بخش به روش هماهنگ کردن چند Promise میپردازیم.
اگر لازم است که Promise-های مختلف را با یکدیگر هماهنگ کنید، میتوانید از متد ()Promise.all برای تعریف کردن لیستی از Promise-ها استفاده کنید و زمانی که همه آنها حل شدند، تابع دیگری را اجرا کنید.
مثالی از آن به صورت زیر است:
ساختار destructuring assignment در ES2015 نیز اجازه اجرای چنین کاری را میدهد:
البته شما محدود به استفاده از fetch نیستید و میتوانید از هر Promise دیگری نیز استفاده کنید.
این متد زمانی اجرا میشود که اولین Promise که به آن ارسال کردهاید حل شود و callback الصاق شده به آن را یک بار به همراه نتیجه نخستین Promise حل شده اجرا میکند. مثالی از آن به صورت زیر است:
اگر با خطای زیر در کنسول مواجه شدید:
Uncaught TypeError: undefined is not a promise
ابتدا باید اطمینان حاصل کنید که به جای ()Promise از ()new Promise استفاده کردهاید.
جدیدترین رویکرد به تابعهای ناهمگام در جاوا اسکریپت Async و Await است. جاوا اسکریپت در طی مدت بسیار کوتاهی (ES2015) استفاده از Callback را کنار گذاشت و به بهرهگیری از Promise-ها روی آورد. از نسخه ES2017 نیز کدهای ناهمگام در جاوا اسکریپت با استفاده از ساختار async/await سادهتر شدهاند.
تابعهای async ترکیبی از Promise-ها و generatos-ها هستند و اساساً لایه بالاتری از تجرید نسبت به Promise محسوب میشوند. در اینجا باید یک بار دیگر تکرار کنیم که async/await بر مبنای Promise-ها ساخته شدهاند.
تابعهای Async/Await باعث کاهش حجم کد مورد نیاز برای نوشتن Promise-ها میشوند و محدودیت «عدم قطع زنجیره» Promise-های زنجیرهسازی را نیز مرتفع میسازند. زمانی که Promise-ها در نسخه ES2015 معرفی شدند، هدف از ارائه آنها حل مشکلی در کدنویسی ناهمگام بود و در این کار نیز موفق بودند، اما در طی دو سال که بین عرضه نسخههای ES2015 و ES2017 وجود داشت مشخص شد که Promise-ها نمیتوانند راهحل نهایی باشند.
Promise-ها برای حل مشکل مشهور جهنم callback-ها عرضه شدند، اما آنها نیز پیچیدگی خاص خود را داشتند و از نظر کاربران دارای ساختار پیچیدهای بودند. Promise-ها با این کارکرد که به ما نشان دادند میتوان از ساختار مناسبتری به این منظور استفاده کرد مفید بودند و لذا اینک زمانی فرا رسیده است که از تابعهای async استفاده کنیم. تابعهای async/await موجب میشوند کد همگام به نظر برسد، اما اساساً ناهمگام است و در پشت صحنه به روشی غیر مسدودکننده عمل میکند.
تابع async یک Promise بازگشت میدهد. به مثال زیر توجه کنید:
زمانی که بخواهیم این تابع را فراخوانی کنیم یک await آماده میکنیم و کد فراخوانی کننده متوقف میشود تا این که Promise حل یا رد شود. تنها الزام این است که تابع کلاینت باید به صورت async تعریف شود. به مثال زیر توجه کنید:
در مثال ساده زیر از async/await برای اجرای ناهمگام یک تابع استفاده شده است:
کد فوق عبارت زیر را در کنسول مرورگر نمایش میدهد:
BeforeAfterI did something //after 3s
الصاق کردن کلیدواژه async به هر تابعی به این معنی است که تابع یک Promise بازگشت خواهد داد. حتی اگر این کار به طور صریح انجام نشده باشد، این کار موجب میشود که تابع به صورت درونی یک Promise بازگشت دهد. به همین دلیل است که کد زیر معتبر است:
این کد نیز مانند کد فوق است:
چنان که در مثال فوق میبینیم، کد ما بسیار ساده به نظر میرسد. آن را با کدی که از Promise-های ساده استفاده میکرد و از زنجیرهسازی و تابعهای callback بهره میگرفت مقایسه کنید. این یک مثال بسیار ساده است، مزیت اصلی زمانی بروز مییابد که کد بسیار پیچیدهتر باشد. برای نمونه با استفاده از Promise-ها به صورت زیر میتوان یک منبع JSON را دریافت کرده و آن را تحلیل کرد:
کد زیر همان کارکرد فوق را با استفاده از await/async اجرا میکند:
تابعهای Async را میتوان بسیار ساده به هم زنجیر کرد و ساختار آن نسبت به Promise-های ساده بسیار خواناتر است:
کد فوق عبارت زیر را نمایش میدهد:
I did something and I watched and I watched as well
دیباگ کردن Promise-ها دشوار است زیرا دیباگر روی کد ناهمگام نمیایستد. اما async/await کار دیباگ را بسیار آسانتر ساختهاند، زیرا از نظر کامپایلر آنها کد همگام هستند.
با استفاده از Event Emitter در Node.js میتوان رویدادهای سفارشی ایجاد کرد. اگر با جاوا اسکریپت در مرورگر کار کرده باشید، میدانید که بخش عمده تعامل با کاربر از طریق رویدادهایی مانند کلیکهای ماوس، فشردن کلیدهای کیبورد، واکنش به حرکت ماوس و غیره مدیریت میشود. در سمت بکاند، Node.js کلاس EventEmitter را ارائه کرده است که برای مدیریت رویدادها استفاده میشود. این کلاس را میتوان با استفاده از کد زیر مقداردهی کرد:
این شیء متدهای on و emit برخی متدهای دیگر را عرضه میکند.
برای نمونه، یک رویداد start ایجاد میکنیم و از آنجا که میخواهیم مثال سادهای باشد، واکنش ما به آن لاگ کردن پیامی در کنسول است:
زمانی که رویداد را اجرا کنیم:
تابع دستگیره رویداد تحریک میشود و لاگ کنسول ایجاد میشود. با استفاده از آرگومانهای اضافی ()emit میتوان آرگومانهایی به دستگیره رویداد ارسال کرد:
شیء EventEmitter چند متد دیگر نیز برای تعامل با رویدادها در اختیار ما قرار میدهد که از آن جملهاند:
بدین ترتیب به پایان بخش هفتم از راهنمای جامع Node.js میرسیم. در بخش بعدی این راهنما در مورد پروتکل HTTP و طرز کار با آن در محیط Node صحبت خواهیم کرد. برای مطالعه بخش بعدی به لینک زیر مراجعه کنید:
ا
منبع: فرادرس
در این مطلب، برنامه محاسبه e به توان عدد x ارائه شده است. محاسبه مقدار تابع نمایی ex با استفاده از «سری تیلور» (Taylor Series)، به صورت زیر، امکانپذیر است.
e^x = 1 + x/1! + x^2/2! + x^3/3! + ......
پرسشی که اکنون مطرح میشود این است که چگونه میتوان به صورت کارا، مجموع سری بالا را محاسبه کرد. سری را میتوان به صورت زیر نوشت:
e^x = 1 + (x/1) (1 + (x/2) (1 + (x/3) (........) ) )
مجموعی که نیاز به محاسبه آن برای n عبارت وجود دارد را میتوان با استفاده از حلقهای که در زیر آمده، محاسبه کرد.
for (i = n - 1, sum = 1; i > 0; --i ) sum = 1 + x * sum / i;
در ادامه، پیادهسازی راهکار بالا در زبانهای برنامهنویسی ++C/C، «جاوا» (Java)، «پایتون 3» (Python 3)، «سیشارپ» (#C) و«پیاچپی» (PHP) انجام شده است. برای آشنایی بیشتر با عدد e، مطالعه مطلب «توابع نمایی و عدد e — به زبان ساده» و همچنین، برای آشنایی بیشتر با سری تیلور، مطالعه مطلب «سری تیلور — از صفر تا صد» توصیه میشود.
همانطور که مشهود است، در قطعه کدهای بالا (همه کدهای ارائه شده برای زبانهای گوناگون شامل پایتون، جاوا، ++C و سیشارپ)، مقدار x برابر با 1 وارد شده است. در نتیجه، خروجی قطعه کدهای بالا به ازای x=1، برابر با مقدار ارائه شده در زیر است.
e^x = 2.718282
ا
منبع: فرادرس