<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>پست‌های انتشارات اسنپ فود</title>
        <link>https://virgool.io/snappfood/feed</link>
        <description>قهرمان قصه‌ای باش که می‌سازی!</description>
        <language>fa</language>
        <pubDate>2026-06-16 07:20:37</pubDate>
        <image>
            <url>https://files.virgool.io/upload/publication/fzp15ln052yv/n9rzzc.png</url>
            <title>اسنپ فود</title>
            <link>https://virgool.io/snappfood</link>
        </image>

                    <item>
                <title>جستجوی دقیق تر با عملگرهای گوگل (Google Search Operators)</title>
                <link>https://virgool.io/snappfood/%D8%AC%D8%B3%D8%AA%D8%AC%D9%88%DB%8C-%D8%AF%D9%82%DB%8C%D9%82-%D8%AA%D8%B1-%D8%A8%D8%A7-%D8%B9%D9%85%D9%84%DA%AF%D8%B1%D9%87%D8%A7%DB%8C-%DA%AF%D9%88%DA%AF%D9%84-google-search-operators-us8endjb4zqx</link>
                <description>تا حالا شده دنبال یه چیزی در گوگل بگردی و نتیجه دلخواهت رو پیدا نکنی؟ یا بخوای محدوده جستجوی خودت رو محدود به یه سایت یا تاریخ مشخصی بکنی؟ در ادامه میخوام در مورد عملگر های گوگل بیشتر صحبت کنم.عملگر های پر کاربرد و فعالبرخی از عملگر ها در حال حاضر قابل‌استفاده نیستند. در ادامه عملگر هایی که در حال حاضر فعال هستند رو بیان میکنم.علامت نقل‌قول یا دبل کوتیشن (&quot; &quot;)شما با استفاده از این عملگر میتوانید دقیقا کلمه موردنظر خودتون رو جستجو کنید. به‌عنوان‌مثال:&quot;گزارش اسنپ فود&quot;زمانی که شما عبارت بالا رو در گوگل جستجو کنید موتور جستجو فقط صفحاتی رو به شما نمایش میده که دقیقا این عبارت در صفحه به کار رفته باشد.جستجو با عملگرنمونه جستجو بدون عملگرعملگر جستجو بر اساس نوع فایل (filetype:)این عملگر میتونه نتایج رو بر اساس نوع فایل براتون فیلتر کنه. به‌عنوان‌مثال:‌ filetype:pdf گزارش اسنپتمامی نتایجی که به شما نمایش داده خواهد شد از نوع فایل های PDF موجود در سطح وب خواهد بود.نمونه جستجو با عملگر نمونه جستجو بدون عملگر عملگر جستجو بر اساس سایت خاص (site:)زمانی که نیاز دارید تمامی نتایج از یک سایت خاص باشند شما میتونید از این عملگر استفاده کنید. به‌عنوان‌مثال: site:snappfood.ir رژیمینتایجی که با جستجوی عبارت بالا به شما نمایش داده میشه صفحاتی از سایت اسنپ فوده که کلمه با کلمه رژیمی ارتباط معنایی داره.نمونه جستجو با عملگرنمونه جستجو بدون عملگرنکته: میشه از این عملگر ها به صورت همزمان استفاده کرد. مثل: site:snappfood.ir &quot;رژیمی&quot; تا صفحاتی که دقیقا از کلمه رژیمی استفاده کرده اند نمایش داده بشه.عملگر جستجو بر اساس عنوان صفحه (intitle:)این عملگر تنها نتایجی رو به شما نمایش میده که در عنوان محتوا از کلمه مورد نظر شما استفاده شده باشه. به‌عنوان‌مثال: intitle:کد تخفیف اسنپ فودعملگر جستجو بر اساس تاریخ (before: و after:)اگه نیاز دارید تا اطلاعات رو بر اساس تاریخ انتشار محدود کنید میتونید از این عملگر استفاده کنید. به‌عنوان‌مثال: اسنپ فود after:2023-06-29نکته: میتوانید با استفاده از علامت - (منهی) برخی از صفحات رو از نتایج پاک کنید. مثل: اسنپ فود after:2023-06-29 -site:snappfood.irشما با جستجو عبارت بالا نتایج بعد از تاریخ مشخص شده به جز سایت snappfood.ir رو خواهید دید.نمونه جستجو با عملگر هاعملگرهای بیشتری هم وجود داره، اگه دوست دارید و اطلاعات بیشتری کسب کنید میتونید به سایت Ahrefs مراجعه کنید.عباس قاسمی هستم. کارشناس برند کارفرمایی اسنپ فود.</description>
                <category>اسنپ فود</category>
                <author>عباس قاسمی</author>
                <pubDate>Wed, 31 Jul 2024 11:39:23 +0330</pubDate>
            </item>
                    <item>
                <title>شنیدن از همکارها کار راحتیه ولی مهم‌تر از اون، عمل کردن به یافته‌هامونه.</title>
                <link>https://virgool.io/snappfood/%D8%B4%D9%86%DB%8C%D8%AF%D9%86-%D8%A7%D8%B2-%D9%87%D9%85%DA%A9%D8%A7%D8%B1%D9%87%D8%A7-%DA%A9%D8%A7%D8%B1-%D8%B1%D8%A7%D8%AD%D8%AA%DB%8C%D9%87-%D9%88%D9%84%DB%8C-%D9%85%D9%87%D9%85-%D8%AA%D8%B1-%D8%A7%D8%B2-%D8%A7%D9%88%D9%86-%D8%B9%D9%85%D9%84-%DA%A9%D8%B1%D8%AF%D9%86-%D8%A8%D9%87-%DB%8C%D8%A7%D9%81%D8%AA%D9%87-%D9%87%D8%A7%D9%85%D9%88%D9%86%D9%87-v6kxd5f71em1</link>
                <description>یکی از کارهایی که ما همکاران منابع انسانی علاقه‌مندیم که انجام بدیم، برگزار کردن نگرش‌سنجی‌هاست. این نگرش‌سنجی‌ها به این دلیل انجام می‌شن که از حال و هوای همکارانمون در سازمان با خبر بشیم. ولی خیلی وقت‌ها از این نکته غافل می‌شیم که نگرش‌سنجی با انتخاب مدل درست و تحلیل درست اون، تنها ۵۰ درصد مسیره و بقیه مسیر اینه که از یافته‌هامون پروژه‌هایی رو تعریف کنیم تا در راستای بهبود تجربه همکارانمون قدم برداریم.رویکردهای نگرش‌سنجیبرای نگرش‌سنجی دو رویکرد وجود داره: بلندمدت (۶ ماهه یا سالانه) و کوتاه‌مدت (Pulse Survey).کارکرد اصلی نگرش‌سنجی بلندمدت برای رسیدن به مسائل اصلیه، این که بدونیم هر تیم چه مساله‌ای داره و کارکرد پرسشنامه کوتاه‌مدت هم برای چک کردن مسیر عملکردمون در اقدامات بهبودبخشیه که می‌تونه هفته‌ای یا ماهانه باشه و نهایتا با یک یا دو سوال پرسیده می‌شه.مدل‌های نگرش‌سنجیبرای نگرش‌سنجی مدل‌های مختلفی وجود داره که تو سرفصل‌های مختلف، تجربه همکاران رو اندازه‌گیری می‌کنه.تمرکز مدل Korn Ferry (هی گروپ) روی توانمندسازها و تعلق سازهاست.تمرکز مدل Q12 Gallup روی نیازهای اولیه، تاثیرگذاری فردی، کار تیمی و رشده.تمرکز مدل Towers Watson روی توانمندسازها و تعلق‌سازها و انرژی‌بخش‌هاست!تمرکز مدل AON Hewitt هم روی روال‌های شرکت، نیازهای اولیه، ماهیت کار، مدیریت عملکرد، مدیران سازمان و برند کارفرمایی سازمانه.ما تو اسنپ‌فود از ترکیبی از این چند مدل استفاده می‌کنیم که نیازمندی‌هامون رو پوشش میده.دسته‌بندی سوالات ما در اسنپ‌فود رو این موارد متمرکزه:فرهنگ سازمان، ماهیت کار، رشد و پیشرفت، تیم و مدیر، سازمان و مدیریت و سوال eNPS.سوال eNPSدر سوال eNPS، می‌پرسیم که از ۰ تا ۱۰ چقدر امکان داره که کار کردن در شرکت رو به دوستانتون توصیه کنید؟منبع: یکتانتنمره‌دهنده‌ها تو سه دسته بالا دسته‌بندی می‌شن که با فرمول پایین می‌تونیم عدد eNPSمون رو به دست بیاریم.منبع: یکتانتاین عدد اگر بین -۱۰ تا +۲۰ باشه معقوله و اگر کمتر باشه وضعیت خیلی قرمزه و اگه بالاتر از ۲۰ باشه هم خوبه و هر چی بیشتر بهتر.اقدامات ما در اسنپ‌فودما در اسنپ فود هر ۶ ماه، نگرش‌سنجی فودپالس رو برگزار می‌کنیم و برای هر دپارتمان داشبورد اختصاصی طراحی می‌کنیم. اما این نگرش‌سنجی دو سوال باز هم داره که با روش تحلیل تم، کدگذاری و جمع‌بندی می‌شه. بعد از اون، لیست اقدامات تعریف شده با توجه به تحلیل‌های به دست اومده رو اولویت‌بندی می‌کنیم.در مرحله بعد جلسه‌ای با معاونان هر واحد و شریک‌های تجاری منابع انسانی اون واحد برگزار می‌کنیم تا نظرات اونها رو هم بر روی یافته‌هامون جویا بشیم.در مرحله بعدی جلسه گفتگوی نیمه‌ساختاریافته‌ای با تعدادی از همکاران هر واحد می‌گذاریم تا یافته‌هامون رو عمیق‌تر بررسی کنیم و نظرات همکاران رو روی اقدامات بهبودبخشی بشنویم.قدم بعدی تهیه کردن لیست اقداماتیه (Action Plan) که در سطح هر واحد و سازمان می‌تونیم داشته باشیم.بعد از اون هم برنامه‌ریزی برای اجرای اقدامات و در نهایت اطلاع‌رسانی اون از طریق برگزاری تاون‌هال به همکاران هر تیم و در نهایت کل سازمانه.اولین‌بار که نگرش‌سنجی فودپالس رو در اسنپ‌فود برگزار کردیم، دو پروژه مهم تعریف شد، راه‌اندازی سیستم ارزیابی عملکرد و پلتفرم قدردانی که در حال حاضر داریم روی اونها کار می‌کنیم و مسیر توسعه‌شون و نتایجش رو حتما با شما عزیزان به اشتراک می‌گذاریم.کلام آخردرسته مسئولیت کلی این پروژه با تیم منابع انسانیه ولی قطعا برای به ثمر نشستنش نیاز به همراهی همه همکارها و مدیران سازمان وجود داره. تا همکاران مشارکت نکنند و آزادانه نظراتشون رو نگن ما از تجربه واقعی‌شون مطلع نمی‌شیم و تا مدیران همراهی‌مون نکنند، نمی‌تونیم تجربه بهتری برای همکارانمون بسازیم.این مسیر پر چالشه ولی امیدواریم بتونیم به بهترین شکل با همراهی همه همکاران انجامش بدیم.</description>
                <category>اسنپ فود</category>
                <author>صادق اشرفی</author>
                <pubDate>Tue, 23 Jan 2024 17:56:15 +0330</pubDate>
            </item>
                    <item>
                <title>Career Page اسنپ‌فود چگونه متولد شد؟</title>
                <link>https://virgool.io/snappfood/career-page-%D8%A7%D8%B3%D9%86%D9%BE-%D9%81%D9%88%D8%AF-%DA%86%DA%AF%D9%88%D9%86%D9%87-%D9%85%D8%AA%D9%88%D9%84%D8%AF-%D8%B4%D8%AF-ot6s6po69wdb</link>
                <description>Career Page چیه؟هر شرکتی برای جذب و استخدام به صفحه‌ای نیاز داره تا موقعیت‌های شغلی باز خودش رو به اطلاع کارجو‌ها برسونه. ساده ترین تعریف برای Career Page می‌تونه همین صفحه با لیستی از موقعیت‌های شغلی باز شرکت باشه. اما ماجرا به همین جا ختم نمیشه!همیشه موقعیت‌های شغلی توی سایت‌های کاریابی منتشر می‌شده و کارشناس‌های جذب و استخدام رزومه‌های دریافتی در این وبسایت‌ها رو دانلود و بررسی می‌کردند. اگه رزومه مناسب باشه وارد روند جذب میشه. مدیریت این روند همیشه سخت بوده؛ هرکسی به نوعی این روند رو مدیریت می‌کرده که مطمئن ترینش با استفاده از اکسل بوده.شاید مدیریت موقعیت‌های شغلی یک شرکت با ۱۰۰ نفر کارمند کار راحتی باشه اما اگه تعداد کارمندهای شرکت بالای ۱۰۰۰ نفر باشه و در لحظه بیش از ۸۰ موقعیت شغلی باز و ۴۰۰ نفر کارجو توی روند جذب داشته باشیم چه طور؟ بازم کار راحتیه؟اگه اصولی از اکسل استفاده کنید احتمالا بتونید این تعداد کارجو رو مدیریت کنید اما ما توی اسنپ‌فود همیشه به راه حل‌های بهینه فکر کردیم و این راه حل بهینه برای مدیریت جذب و استخدام استفاده از ATS (سیستم ردیابی کارجو) بود.چرا به Career Page نیاز داشتیم؟همونطور که گفتم ما در اسنپ‌فود برای مدیریت فرآیند جذب و استخدام از ATS (سیستم ردیابی کارجو) استفاده می‌کنیم. توی این سیستم همه پوزیشن‌های باز با جزییات درج میشه و فرمی در اختیار کارجو قرار می‌گیره تا اطلاعات و رزومه خودش رو آپلود کنه. اطلاعات کارجو بدون دخالت هیچ شخصی وارد روند جذب میشه. با وجود ATS هیچ کارجویی فراموش نمیشه و از طرفی زمان بررسی و اعلام نتیجه کاهش پیدا میکنه.به سیستم ATS همه افرادی که باید با کارجو مصاحبه انجام بدن و تاییدیه ارسال کنند دسترسی دارن و در نتیجه روند جذب با نظم و طبق اصول پیش میره.این وسط یه حلقه گم شده وجود داره و اون Career Page هست. Career Page اینجا وارد مسئله میشه تا بین کارجو و ATS قرار بگیره.ما به صفحه‌ای نیاز داشتیم تا علاوه بر نمایش لیست موقعیت‌های شغلی باز، ویترین برند کارفرمایی اسنپ‌فود باشه. این صفحه باید اطلاعات دیگه‌ای مثل مزیت‌های همکاری با اسنپ‌فود، محیط کاری، فرهنگ سازمانی و… رو هم توی دید کارجو قرار بده تا با دید بازتری رزومه خودش رو برای ما ارسال کنه و تجربه بهتری برای همکاری با ما داشته باشه.از طرف دیگه ما معتقدیم هر کدوم از همکارانمون توی موقعیت شغلی خودشون یه ابرقهرمان هستند که بهترین‌ها رو رقم می‌زنند و می‌خوایم کارجو‌ها از ابتدای روند جذب با این کانسپت آشنا بشن.از کجا شروع کردیم؟اولین قدم ما نیازسنجی بود. ابتدای راه با کمک صادق اشرفی عزیز، با چند نفر که در موقعیت کاریابی بودند مصاحبه کردیم و نیاز‌های اون‌ها رو از یک صفحه فرصت‌های شغلی به دست آوردیم. توی مرحله بعد به سراغ ذینفعان رفتیم و نیاز‌های اون‌ها رو هم به دست آوردیم.مرحله بعدی بنچ مارک یا مطالعه نمونه‌های مشابه بود. متاسفانه نمونه‌های مشابه خوبی رو توی وب فارسی پیدا نکردیم که بتونه به ما در این زمینه کمک کنه. نمونه‌هایی وجود داشت اما به اون حدی نبود که انتظارات ما رو برآورده کنه. پس ناچارا به سراغ نمونه‌های خارجی رفتیم.بعد از اینکه همه نمونه‌ها رو بررسی کردیم و نیازمندی‌ها هم مشخص شد وقتش بود که طراحی رو شروع کنیم.در این مسیر سیاوش قنبرزاده عزیز چندتا طرح اولیه طراحی کرد و MVP رو ارائه کردیم.اینجای کار علاوه بر دیزاین Career Page باید زیرساخت رو هم مشخص می‌کردیم. ما دوتا راه داشتیم؛ راه اول این بود که به صورت اختصاصی برنامه نویسی می‌کردیم که هزینه و زمان زیادی از ما می‌گرفت و راه دیگه استفاده از CMS بود.از اونجایی که ما نیاز داشتیم طراحی و مدیریت این صفحه درون دپارتمان HR انجام بشه که به همین علت وردپرس رو به عنوان یه CMS انتخاب کردیم. اصلی ترین دلیل انتخاب وردپرس هزینه کم، مدیریت و توسعه ساده‌تر اون بود. ما با استفاده از وردپرس به راحتی می‌تونستیم دیزاین مورد نظر خودمون با تمام ویژگی‌های مورد نیاز رو طراحی و پیاده سازی کنیم و برای مدیریتش به دپارتمان‌های دیگه وابستگی نداشتیم.توی نسخه اولیه فقط موقعیت‌های شغلی باز رو به صورت لیست نمایش دادیم. برای نمایش لیست از API که ATS در اختیارمون قرار داده بود استفاده کردیم و در نهایت طرح اولیه لیست موقعیت‌های شغلی به صورت زیر شد:توسعه Career Pageنسخه اولیه که برای Career Page طراحی کردیم الزامات اولیه رو داشت اما کافی نبود. ما انتظارات دیگه‌ای هم از این سایت داشتیم. در ادامه چند نمونه از توسعه‌هایی که انجام دادیم رو نوشتم.API دریافت پوزیشنهمونطور که گفتم ما در اولین نسخه Career Page اسنپ‌فود فقط لیست موقعیت شغلی‌های باز رو نشون می‌دادیم و در نهایت برای نمایش جزییات دقیق موقعیت شغلی، کاربر رو به صفحه‌ای که ATS طراحی کرده بود هدایت می‌کردیم. به صورت خلاصه تر ما توی نسخه اولیه فقط اطلاعات رو توی یک تک صفحه نمایش می‌دادیم که هر مرتبه با ورود کاربر به اون صفحه، لیست با API دریافت میشد و با دیزاین مورد نظر ما با استفاده از کد JS لود میشد.طراحی پلاگین دریافت و آپدیت اطلاعات موقعیت‌های شغلیتوی مدت زمانی که از MVP استفاده می‌کردیم با استفاده از دیتای آنالیتیکس متوجه شدیم که کاربران سایت بعد از اینکه برای مشاهده توضیحات موقعیت شغلی از Career Page خارج و به صفحه طراحی شده توسط ATS وارد میشن دیگه برای مشاهده دیگر موقعیت‌ها به Career Page برنمی‌گردند در صورتی که باز هم موقعیت‌های مشابه توی لیست وجود داشت!بعد از بررسی نقشه سفر کارجو و سناریو‌های احتمالی متوجه شدیم که هیچ لینک برگشتی از سمت ATS به Career Page وجود نداره و علارغم درخواست‌های مکرر به ATS، هیچی لینکی در ATS برای بازگشت کارجو اضافه نشد!با توجه به این شرایط تصمیم گرفتیم که توضیحات موقعیت‌های شغلی رو هم درون خود Career Page نمایش بدیم. طبق تجربه قبلی تصمیم گرفتیم توضیحات رو هم با استفاده از JS نمایش بدیم اما اینجا به یک چالش برخوردیم و اون تفاوت دیتای موقعیت‌های شغلی فارسی و انگلیسی بود! با استفاده از کدی که نوشته بودیم صفحات توضیحات موقعیت شغلی خیلی کند لود میشد و عملا غیرقابل استفاده بودند.از طرفی دیگه Career Page اصلی ترین کانال ما برای دریافت رزومه و اطلاعات کارجو‌ها بود؛ پس نیاز بود که از ظرفیت سئو هم استفاده کنیم. با توجه به اینکه هیچ صفحه‌ توضیحات موقعیت شغلی در Career Page وجود نداشت این امکان برای ما فراهم نبود.سه دلیل اصلی یعنی برنگشتن کارجو‌ها از ATS، لود کند صفحات ساخته شده با JS و محدودیت‌های سئو به این فکر افتادیم تا توضیحات و جزییات موقعیت‌های شغلی رو در دیتابیس Career Page ذخیره کنیم و با طراحی یک پست تایپ جدید در وردپرس، توضیحات رو درون خود Career Page نمایش بدیم.توی این مرحله از پروژه به فکر طراحی یک پلاگین وردپرس افتادیم تا همه این موارد رو برای ما پوشش بده.طبق انتظاری که داشتیم پلاگین مشکل ما رو حل کرد و تونستیم موارد موجود رو حل کنیم.تصویر شاخص لینک‌های موقعیت شغلیمزیت دیگه پلاگینی که طراحی کردیم این بود که برای موقعیت شغلی یه کاور طراحی کردیم و با انتشار لینک موقعیت‌ها، کاور مورد نظر ما هم همراه لینک نمایش داده میشه.جذب کارجو از طریق سئوجالب ترین مزیتی که پلاگین برای ما داشت این بود که با فعال شدنش، ورودی ارگانیک گوگل (سئو) هم ۲ تا ۳ برابر رشد کرد.همچنین به لطف پلاگین، تونستیم اسکیمای jobposting رو هم فعال کنیم و از ظرفیت گوگل بهتر بهره ببریم.ارسال موقعیت شغلی برای دوستانیکی از فیچر‌های ساده اما جذابی که به صفحه موقعیت شغلی اضافه کردیم، معرفی به دوستان هست. کارکردش هم به این صورته که با وارد کردن نام خودتون، نام دوستتون و شماره همراهش یک پیامک حاوی لینک موقعیت شغلی برای دوستتون ارسال میشه.این مسیر همچنان ادامه داره...طراحی ویژگی‌های جدید و همچنین باز طراحی وبسایت موقعیت‌های شغلی اسنپ‌فود با توجه به بازخورد‌ها و همچنین نیاز‌های جدید همچنان ادامه داره. شاید در ادامه توی یه پست دیگه در مورد ری‌دیزاین این سایت نوشتم.شما هم اگه پشنهادی برای بهتر شدن این وبسایت دارید خوشحال میشم که زیر همین پست و یا در لینکدین بهم بگید.لینکدین من: https://www.linkedin.com/in/imfarhadiدر آخر خالی از لطف نیست که به این وبسایت سری بزنید و اگه موقعیت شغلی مناسب خودتون رو دیدید، رزومتون رو برای ما ارسال کنید. ما خوشحال میشیم که متخصص‌های توانمند رو کنار خودمون داشته باشیم.بیاید تا توی اسنپ‌فود قهرمان قصه‌ای بشید که خودتون می‌سازید.https://careers.snappfood.irمنتطرتون هستیم 😉</description>
                <category>اسنپ فود</category>
                <author>مهران فرهادی</author>
                <pubDate>Sat, 09 Dec 2023 13:07:32 +0330</pubDate>
            </item>
                    <item>
                <title>به تماشای پرواز</title>
                <link>https://virgool.io/snappfood/census-of-birds-of-prey-yemfztmkt6fd</link>
                <description>برای اینکه بتونیم زندگی با کیفیت‌تری داشته باشیم، نیازه که بین کار، تفریح و زندگی شخصی یه تعادل نسبی برقرار کنیم و از شرایط موجود لذت ببریم. تفریح یکی از نیازهای اصلی هر کدوم از ماهاست که اگه به خوبی ازش استفاده کنیم، روی ابعاد دیگه زندگی به خصوص کار تاثیر مثبت زیادی می‌ذاره. حالا چه خوب میشه که انجام مسئولیت‌های اجتماعی یکی از تفریح‌های ما باشه.علی موسوی یکی از بچه‌های فعال اسنپ‌فوده که بخشی از زمان خودش رو به یه مسئولیت اجتماعی جذاب اختصاص داده.بریم از زبون خودش بشنویم چیکار کرده:احتمالاً خیلی تعجب می‌کنید اگه بشنوید که چندتا جوون ایرانی به مدت ۸۰ روز از طلوع تا غروب آفتاب بدون دریافت حقوق زیر آفتاب و بارون و طوفان، پرنده شکاری شمارش می‌کنن.پروژه شمارش پرندگان شکاری گلوگاه (شهر گلوگاه مازندران) اولین پروژه شمارش پرندگان شکاری در ایران و یکی از مهمترین پروژه‌های شمارش این پرندگان در اورآسیا (اروپا و آسیا) به حساب میاد. پروژه‌ای کاملاً داوطلبانه که با کمک‌های مردمی و حمایت اسپانسر تامین مالی میشه و سه سال از عمرش می‌گذره.بله ما پرنده شکاری شمارش می‌کنیم. کاری که چندان معمول نیست اما به شدت مهم، جذاب و هیجان‌انگیزه. اما اینکه چرا این کار رو انجام می‌دیم برمی‌گرده به نقش پرندگان شکاری (عقاب‌ها، کرکس‌ها، قوش‌ها، شاهین‌ها و …) در هرم غذایی حیات وحش و اهمیت این گونه‌ها در حفاظت از محیط زیست.پرندگان شکاری هر سال دو بار، یک مرتبه در بهار از آفریقا و خاورمیانه به روسیه و آسیای مرکزی و یک بار در پاییز همین مسیر رو در مهاجرتی طولانی به عرض‌های جنوبی‌تر زمین برمی‌گردن. گونه‌های بزرگ این پرندگان (عقاب‌ها و کرکس‌ها) به دلیل وزن قابل توجه (نسبت به بقیه گونه‌های پرنده) و مسافت زیاد مهاجرت، معمولاً در مسیر مهاجرت خیلی کم از قدرت بال‌زنی استفاده کرده و سعی می‌کنن از جریانات هوای گرم برای طی مسافت بهره ببرن.جریانات هوای گرم حاصل بازتاب خورشید به زمین هستن. دقیقاً همون گرمایی که پالاگرایدرها برای بالا رفتن ازش استفاده می‌کنن. این هوای گرم معمولاً در پهنه‌های آبی (دریاها، رودخانه‌ها و تالاب‌ها) وجود نداره یا خیلی ضعیف و پراکنده هست. نتیجه این توضیح اینکه، در جایی مثل گوشه جنوب شرقی دریای کاسپین (مرز بین استان‌های مازندران و گلستان) به دلیل وجود این پهنه آبی وسیع و کوه‌های البرز، پرنده‌های شکاری عبور از خشکی‌های شرق دریا را ترجیح داده و در مسیر به کوه‌های البرز برخورد می‌کنن. ارتفاعاتی که برای عبور از آن‌ها لازمه تا جریانات هوا به قدر کافی قوی بشن. دقیقاً این موقعیت و لحظه‌ای هست که این فرصت رو به ما میده تا پرنده‌ها رو که مجبور به عبور از این گلوگاه مهاجرتی هستن، شمارش کنیم. این اجبار به عبور از گلوگاهی خاص در یک منطقه، چیزی شبیه استفاده ما از خطوط مترو هست. ساختاری که ایجاد شده و ما فارغ از نسبت‌های فامیلی، تفاوت مسیر و … مجبور به استفاده از این زیرساخت‌ها و پیاده شدن در ایستگاه‌های مختلف هستیم.حدود ۲۰ گونه پرنده شکاری از این گلوگاه مهاجرتی عبور می‌کنن. پرنده‌ها از مسیرهای مختلف و در فواصل متفاوت وارد گلوگاه شده و با توجه به شدت گرما، میزان ابری بودن هوا و سرعت باد بعد از چند دقیقه یا چند ساعت از گلوگاه خارج میشن. نوع گونه، سن و گاهی جنسیت شکاری‌های عبوری در حد امکان تعیین میشه (با توجه به فاصله‌ای که از محل استقرار تیم شمارش دارن). کافیه این تنوع گونه‌ها رو در زمان متفاوت شروع مهاجرت، تعداد متفاوت هر گونه، روش‌های شناسایی و مشخصات ظاهری مختلف و حداقل سه رده سنی مختلف، ضرب کنید تا به میزان پیچیدگی، سختی و البته جذابیت امور فنی شمارش پی‌ ببرید. کاری علمی و تخصصی که در کشورهای منطقه از جمله گرجستان (پروژه شمارش شکاری‌ها در باتومی) توسط پرنده‌شناسان و علاقه‌مندان اروپایی صورت می‌گیره اما در اینجا یعنی گلوگاه مازندران بطور کامل توسط ما بچه‌های ایران و با کیفیت بسیار خوب انجام میشه.ارزیابی جمعیتی گونه‌های جانوری اولین قدم در شروع راه طولانی و سخت حفاظت هست. تیم اجرایی پروژه در سال سوم یعنی پاییز ۱۴۰۱ شامل ۵ نفر تیم هماهنگ‌کننده و ۳۷ نفر داوطلب از شهرهای مختلف کشور بود. با کمک داوطلبین عزیز پروژه، در طی ۸۰ روز بیش از ۱۰۰ هزار پرنده شکاری شمارش کردیم که بیش از ۶۰ هزار از این پرنده‌ها از گونه‌های عقاب‌های بزرگ‌جثه هستن که این آمارها در کمتر نقطه‌ای از منطقه اورآسیا ثبت شده. پروژه‌های شمارش پرندگان شکاری معمولاً عمرهای بسیار طولانی دارن و در دهه‌های مختلف توسط نسل‌هایی متفاوت اجرا میشن. نتایج شمارش به صورت مرتب در نشریه‌های علمی یا پایگاه‌های داده مرتبط با محیط زیست منتشر شده و توسط تمام کشورهای ذینفع (میزبان پرندگان) قابل استفاده‌ است. علاوه بر این، اجرای چنین پروژه‌هایی که به صورت مشارکتی و داوطلبانه اداره میشن، تاثیر بسیار قابل توجهی بر دانش عمومی مردم، سطح علمی شرکت‌کنندگان و تربیت نسلی آگاه و علاقه‌مند به حفاظت از میراث طبیعی کشورها داره.علی جان از سال ۹۷ در اسنپ‌فود مشغول به کاره و از زمان شروع کرونا، فعالیت خودش رو در زمینه حفاظت از پرندگان ایران افزایش داده. علی به عنوان یکی از اعضای تیم مدیریتی پروژه شمارش پرندگان شکاری گلوگاه تونسته این مسئولیت رو در کنار شرایط کاری اسنپ‌فود ادامه بده…شما هم اگه به حضور در این پروژه علاقه‌مند بودید باید بدونید که هیچ محدودیتی از نظر میزان آشنایی با پرنده‌ها وجود نداره. حضور هر شخصی می‌تونه حداقل 2 چشم به چشم‌های جست‌و‌جو‌گر اضافه کنه و این کمک بزرگیه. پرنده‌نگری و پرنده‌شناسی آماتوری یکی از جذاب‌ترین زیرشاخه‌های علم شهروندی (Citizen Science) به حساب میاد و با توجه به وسعت و تنوعی که داره می‌تونه حال ساکنین شهرهای بزرگ مخصوصاً کارمندانی که فرصت کمتری برای سفر دارن رو متحول کنه و باعث ایجاد شوق و شوری تازه برای کشف جهان اطراف بشه.علی و دوستانش در این پروژه میزبان تمام علاقه‌مندان به خصوص همکاران عزیزمون در اسنپ‌فود هستند. اینجا بهترین فرصت برای مشاهده و آشنایی با پرندگان و یکی از شگفت‌انگیزترین اتفاقات طبیعت، یعنی مهاجرته.برای ارتباط با علی جان می‌تونید توی اسکایپ پیام بدید( ali.mousavi7 ) و یا به پیج اینستاگرام و سایتشون سر بزنید.اینستاگرام: instagram.com/galugahraptorsوبسایت: galugahraptorcount.org</description>
                <category>اسنپ فود</category>
                <author>مهران فرهادی</author>
                <pubDate>Tue, 29 Aug 2023 11:19:38 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه از هوک‌های ری‌اکت استفاده کنیم؟ - آموزش کامل برای تازه‌کاران</title>
                <link>https://virgool.io/snappfood/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%A7%D8%B2-%D9%87%D9%88%DA%A9-%D9%87%D8%A7%DB%8C-%D8%B1%DB%8C-%D8%A7%DA%A9%D8%AA-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%DA%A9%D9%86%DB%8C%D9%85-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%DA%A9%D8%A7%D9%85%D9%84-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%AA%D8%A7%D8%B2%D9%87-%DA%A9%D8%A7%D8%B1%D8%A7%D9%86-qf3kxt5aaysn</link>
                <description>هوک‌های ری‌اکتسلام به همه!، هوک‌ها یکی از ویژگی‌های اصلی کد ری‌اکت مدرن، و همچنین یکی از مفاهیم پایه‌ای هستند که موقع یادگیری این لایبرری باید باهاش راحت باشید.در این مقاله قصد دارم برخی از مفیدترین هوک‌هایی را که ری‌اکت در اختیار ما می‌گذارد، نحوه کار آن‌ها و مثال‌هایی از موقعیت‌هایی که می‌توانیم از آن‌ها استفاده کنیم را توضیح دهم.امیدوارم که از خواندن این مقاله لذت ببرید. این مقاله ترجمه‌ای از جدیدترین مقاله‌ی freecodecamp هست و امیدوارم که ترجمه‌ی خوبی باشه و این مطلب براتون جا بیوفته.همچنین بد نیست نگاهی به داکیومنت ری‌اکت درباره‌ی هوک‌ها بیندازید.چنانچه بعضی کدها در تصاویر ناخوانا هستند، آن‌ها را در Github Gist نیز گذاشته‌ام.مقداری تاریخچه در مورد ری‌اکت و اینکه هوک‌ها برای چه هستندهمانطور که ممکن است بدانید، ری‌اکت یک لایبرری اوپن سورس است که جهت ساخت UI به روشی ساده‌تر و کارآمدتر از ابزارهای قبلی (مانند vanilla JS و jQuery) استفاده می‌شود. ری‌اکت توسط کمپانی متا (همان فیس‌بوک) توسعه یافت و در سال ۲۰۱۳ برای عموم منتشر شد.هوک‌ها قابلیتی بودند که سال‌ها بعد در سال ۲۰۱۶ (ری‌اکت ورژن ۱۶.۸) معرفی شدند. فقط برای اینکه بدانیم هوک‌ها برای چه چیزی هستند و چرا نسبت به آنچه قبلا انجام شده بود بهبود یافته‌اند، نمونه‌ای از کدهای «پیش از هوک» را در مقابل برخی از کدهای «پس از هوک» ری‌اکت مدرن ببینیم.در کد ری‌اکت قدیمی ما از کلاس کامپوننت‌ها استفاده می‌کردیم. اون‌ها یک متد render حاوی JSX داشتند که مسئول رندر کردن UI است.و اگر می‌خواستیم این کامپوننت stateای را ذخیره کند، باید آن را در یک متد constructor تعریف می‌کردیم و با فراخوانی this.setState آن را تغییر می‌دادیم. در زیر یک مثال کوتاه برای شما جهت پیدا کردن ایده وجود دارد:مثالی از کلاس کامپوننتاین خیلی مهم هست که اشاره کنیم که فانکشن کامپوننت‌ها (چیزی که امروزه استفاده می‌کنیم) در زمان ری‌اکت «پیش از هوک» نیز وجود داشتند. اما فقط می‌توانیم از آن‌ها برای کامپوننت‌های stateless استفاده کنیم - به این معنی که کامپوننت‌هایی که state ذخیره نمی‌کنند و مسئولیت هیچ منطق پیچیده‌ای به غیر از رندر کردن UI نیستند.با ادغام هوک‌ها، اکنون می‌توانیم از فانکشن کامپوننت‌ها(و ترکیب ساده‌تر آن‌ها) همراه با همه عملکردهای پیچیده‌تر که کلاس کامپوننت‌ها به ما ارائه می‌دهند، استفاده کنیم.به طور خلاصه، هوک‌ها چیزهایی هستند که ما برای پیاده‌سازی منطق و فانکشنالیتی‌ها در کامپوننت خود استفاده می کنیم.در اینجا مثال دیگری میبینید که ما آنچه را که در کلاس کامپوننت خود داشتیم (مثال بالا) به یک فانکشنال کامپوننت تبدیل کردیم:مثالی از فانکشنال کامپوننتهوک‌های پرکاربرد در ری‌اکتاکنون می‌دانید که هوک‌ها برای چه چیزی هستند و چرا بهتر از قبل شده‌اند. بنابراین بیایید نگاهی به پرکاربردترین آن‌ها بیاندازیم، در چه مواقعی مفید هستند و چگونه آن‌ها را پیاده‌سازی کنیم.هوک useStateدر ری‌اکت مدرن، ما اپلیکیشن‌های خود را با فانکشنال کامپوننت می‌سازیم. کامپوننت‌ها خود توابع جاوااسکریپت، تکه‌های کد مستقل و قابل استفاده مجدد هستند.هدف از ساخت اپلیکیشن با کامپوننت‌ها داشتن معماری ماژولار با تفکیک واضح سطوح مختلف است. این امر درک کد را آسان‌تر، نگهداری آسان‌تر و استفاده مجدد را در صورت امکان آسان‌تر می‌کند.یک state درواقع objectای است که اطلاعات مربوط به یک کامپوننت خاص را در خود نگه میدارد. توابع جاوااسکریپت ساده توانایی ذخیره اطلاعات را ندارند. کد درون آن‌ها اجرا می شود و پس از پایان اجرا «ناپدید» می‌شود.اما به لطف state، فانکشنال کامپوننت‌های ری‌اکت می‌توانند اطلاعات را حتی پس از اجرا ذخیره کنند. وقتی برای ذخیره یا «به خاطر سپردن» چیزی، یا به روشی متفاوت بسته به محیط، به یک کامپوننت نیاز داریم، state دقیقا همان چیزی‌ست که ما به آن نیاز داریم تا این کار را طوری که می‌خواهیم انجام دهد.ذکر این نکته ضروری است که همه‌ی کامپوننت‌های اپلیکیشن ری‌اکتی نباید دارای state باشند. کامپوننت‌های stateless نیز وجود دارند که فقط محتوای خود را بدون نیاز به ذخیره اطلاعات رندر می‌کنند، و این خیلی خوب است.نکته مهم دیگری که باید به آن اشاره کرد این است که تغییر state یکی از دو موردی است که باعث می‌شود یک کامپوننت ری‌اکتی دوباره رندر شود (دیگری تغییر در props است). به این ترتیب، حالت اطلاعات مربوط به کامپوننت را ذخیره می‌کند و همچنین رفتار آن را کنترل می‌کند.برای پیاده‌سازی state در کامپوننت‌مان، ری‌اکت یک هوکی به نام useState در اختیار ما قرار می‌دهد. بیایید با مثال زیر ببینیم چگونه کار می‌کند.مثالی از useStateابتدا هوک را از ری‌اکت ایمپورت می‌کنیم: import { useState } from &#x27;react&#x27;سپس state را مقداردهی اولیه می‌کنیم: const [count, setCount] = useState(0)در اینجا یک نام متغیر برای state (count) و یک نام تابع که هر بار که نیاز به به‌روزرسانی آن state داشته باشیم (setCount) استفاده خواهیم کرد. سپس مقدار اولیه state را (0) تنظیم می‌کنیم که به طور پیش فرض هر بار که برنامه شروع می‌شود، بارگذاری می شود.در نهایت، همانطور که در بالا گفتیم، هر بار که می‌خواهیم state را به‌روز کنیم، باید از تابعی که تعریف کردیم استفاده کنیم: setCount. برای استفاده از آن، فقط باید آن را با پاس دادن state جدیدی که به عنوان پارامتر می‌خواهیم، ​​صدا کنیم. یعنی اگر بخواهیم 1 را به state قبلی اضافه کنیم، setCount(count+1) را صدا می زنیم.همانطور که گفته شد، این باعث به‌روز‌رسانی state و ری‌رندر کامپوننت می‌شود. که در اپلیکیشن‌مان به این معنی‌ست که روی صفحه خواهیم دید که شمارنده در حال بالا رفتن است.ذکر این نکته ضروری است که تابع setState یک تابع asynchronous است. بنابراین اگر سعی کنیم state را بلافاصله پس از به‌روزرسانی آن بخوانیم، مانند زیر:نمونه فانکشن setCount با کلیک بر روی دکمهما مقدار قبلی state را بدون به‌روزرسانی دریافت می‌کنیم.روش صحیح خواندن state پس از به‌روزرسانی، استفاده از هوک useEffect است. این هوک به ما این امکان را می‌دهد که پس از هر ری‌رندر کامپوننت (به طور پیش فرض) یا بعد از هر متغیر خاصی که در آن تغییرات را اعلام می‌کنیم، یک تابع اجرا کنیم.چیزی مثل این:خواندن یک state پس از به‌روزرسانی با استفاده از useEffect همچنین، این واقعیت که useState یک تابع asynchronous است، هنگام در نظر گرفتن تغییرات state بسیار مکرر و سریع، پیامدهایی دارد. این نکته‌ی بسیار مهمی است که همیشه باید در ذهن نگه داریم.به عنوان مثال، موردی را در نظر بگیرید که یک کاربر دکمه ADD را چندین بار پشت سر هم فشار می‌دهد، یا حلقه‌ای که یک رویداد کلیک را چندین بار منتشر می‌کند.با به‌روزرسانی stateای مانند setCount(count+1) ما این خطر را می‌پذیریم که با اجرای رویداد بعدی، count هنوز به‌روزرسانی نشده باشد.برای مثال، فرض کنید در شروع count = 0است. سپس setCount(count+1) فراخوانی می شود و state به طور asynchronous به‌روز می‌شود.اما دوباره setCount(count+1) قبل از تکمیل به‌روزرسانی state فراخوانی می‌شود. این بدان معنی‌ست که هنوز count = 0 است، یعنی که setCount دوم stateمان را به درستی به‌روز نمی‌کند.یک رویکرد تدافعی‌تر این است که به setCount یک callback داده شود، مانند:setCount(prevCount =&gt; prevCount+1)در این حالت مطمئن می‌شویم که مقدار به‌روزرسانی جدیدترین مقدار است و ما را از مشکل ذکر شده در بالا دور نگه می‌دارد. هر بار که می‌خواهیم به‌روزرسانی‌هایی را در state قبلی انجام دهیم، باید از این روش استفاده کنیم.اگر می‌خواهید نگاهی عمیق‌تر به روش‌های مدیریت state در ری‌اکت بیندازید، می‌توانید به این مقاله که چندی پیش نوشته شده نگاهی بیندازید. (به زودی ترجمه آن را خواهم گذاشت.)هوک useEffectبه همراه useState، هوک useEffect احتمالاً هوکی است که بیشتر از همه در هنگام توسعه یک اپلیکیشن ری‌اکت استفاده می‌کنید. این دو مانند نان و کره برای توسعه‌دهنده ری‌اکت است.هوک UseEffect به شما این امکان را می‌دهد که یک اثر جانبی (side effect) روی کامپوننت خود اجرا کنید. اثر جانبی اساساً به معنای چیزی است که پس از وقوع یک چیز خاص دیگر اتفاق می‌افتد.یک مورد معمول استفاده واکشی داده‌ها (fetch data) پس از نصب (mount) کامپوننت است (در اینجا نیاز هست تا لایف سایکل‌ها در ری‌اکت را بلد باشید). فرض کنید ما تابعی به نام fetchData داریم که مسئول آن واکشی است - هوک useEffect ما ممکن است شبیه به این باشد:صدا زدن تابع fetchData داخل هوک useEffectساختار این هوک بسیار ساده است. دو آرگومان را می‌پذیرد. ابتدا یک callback داریم که تابع ما را اجرا می‌کند و سپس یک آرایه به نام «آرایه وابستگی ها» داریم. اگر مانند مثال بالا آن را خالی بگذاریم، بلافاصله پس از رندر شدن کامپوننت، callback اجرا می‌شود.حال فرض کنید می‌خواهیم اثر جانبی (side effect) ما پس از تغییرات متغیر اجرا شود. به دنبال مثال قبلی که برای هوک useState استفاده کردیم، برای اثر جانبی پس از تغییرات متغیر count، می‌توانیم useEffect را به این صورت تنظیم کنیم:به‌روز شدن پیغام کنسول پس از تغییر متغیر Count توسط useEffectسومین و آخرین موردی که در مورد useEffect باید به آن اشاره کرد، امکان بازگشت یک تابع «پاکسازی» است. این تابع «پاکسازی» زمانی که کامپوننت جدا (unmount) شود، اجرا می‌شود. به دنبال مثال قبلی، افزودن یک تابع پاکسازی ممکن است به شکل زیر باشد:بازگشت یک تابع پاکسازی در useEffectتوابع پاکسازی در useEffect معمولاً برای لغو اشتراک‌ها استفاده می‌شوند تا از تلاش ری‌اکت برای به‌روزرسانی state یک کامپوننت که قبلاً unmount شده است، جلوگیری شود.برای اطلاعات بیشتر در مورد تابع پاکسازی در useEffect، می توانید به این مقاله و یا این مقاله مراجعه کنید.هوک useContextدر سال ۲۰۱۶ React context API با نسخه 16.3 ری‌اکت منتشر شد. کاری که context در ری‌اکت انجام می‌دهد، ارائه راه حلی برای prop drilling است.مفهوم prop drilling به موقعیتی اشاره دارد که در آن ما یک کامپوننت والد داریم که یک state را ذخیره می‌کند. و در زیر آن والد، ما سطوح بسیاری از کامپوننت فرزند داریم.اگر بخواهیم آن state را در یک کامپوونت فرزند که عمیقاً در آن ساختار تودرتو (nested) است ارائه کنیم، راه حل این است که state را به عنوان prop در سراسر زنجیره کامپوننت منتقل کنیم.تصویری از prop drilling این گزینه به خوبی کار می‌کند. اما مشکل این است که ما باید همان کد را در جاهای مختلف تکرار کنیم، که اگر بعداً نیاز به تغییر کد خود داشته باشیم (دیر یا زود مجبور خواهید بود این کار را انجام دهید) کار با آن بسیار خسته کننده است و مستعد ایجاد خطاها و اشکالات است.حالا Context API این وضعیت را با ارائه «مکانی» برای ذخیره stateای که باید از بخش‌های مختلف اپلیکیشن‌مان و در امتداد سطوح مختلف درخت کامپوننت استفاده شود را حل می‌کند.روش کار به این صورت است که کامپوننت context آن state داده شده را ذخیره می کند، و از هر کامپوننت داده شده می توانیم آن state را بخوانیم و به‌روز کنیم، مهم نیست که آن کامپوننت در کجا قرار دارد. ما همه propها را فراموش می‌کنیم. در عوض، ما فقط می‌توانیم مستقیماً با context کار کنیم و همه کامپوننت‌هایی که آن context state را می‌خوانند، وقتی وضعیت به‌روزرسانی می‌شود، دوباره رندر می‌شوند.تصویری از همان موقعیت اما با استفاده از context حال که پایه‌های نظری را فهمیدیم، بیایید ببینیم که چگونه هوک useContext به ما اجازه می دهد از این API استفاده کنیم. اجرای معمول چیزی شبیه به این خواهد بود. در یک پوشه به اسم &quot;context&quot; دو فایل خواهیم داشت. Context.js و ContextProvider.js.در Context.js، ما فقط با استفاده از تابع createContext مقدار context API را مقداردهی اولیه می کنیم، که به عنوان آرگومان state اولیه‌ای را که می‌خواهیم ارائه کنیم را ارسال می‌کنیم. (در این مورد چیزی نمی خواهیم، ​​بنابراین می توانیم null را ارسال کنیم).نمونه فایل context.js در ContextProvider.js، آن contextای را که در فایل قبلی مقداردهی اولیه کردیم، ایمپورت می‌کنیم. ما همچنین stateهایی را که می‌خواهیم بعدا استفاده کنیم، مقداردهی اولیه می‌کنیم و از کامپوننت اپلیکشن خود به‌روزرسانی می‌کنیم. در نهایت، context provider را برمی‌گردانیم و با آبجکت value، تمام stateها و توابع setState را که می‌خواهیم بعدا استفاده کنیم، ارسال می‌کنیم.یک ContextProvider درواقع یک HOC است. یک کامپوننت مرتبه بالاتر (higher order component) یا HOC مشابه یک تابع مرتبه بالاتر در جاوا اسکریپت است (من یک مقاله در مورد آن در اینجا دارم).توابع مرتبه بالاتر توابعی هستند که توابع دیگر را به عنوان آرگومان می گیرند یا توابع دیگر را برمی‌گرداند. React HOCها یک کامپوننت را به عنوان یک prop می‌گیرند و آن را تا حدی دستکاری می‌کنند بدون اینکه در واقع خود کامپوننت را تغییر دهند. شما می‌توانید به این مانند کامپوننت‌های wrapper فکر کنید.ContextProviderنمونه فایل  در فایل App.js خود، تمام کامپوننت‌هایی را که می‌خواهیم بتوانیم با state تعامل داشته باشیم، با contextProvider خود می‌پوشانیم (wrap می‌کنیم). در این مورد ما می خواهیم که کل اپلیکیشن بتواند context را استفاده کرده و به‌روز کند، بنابراین همه آن را می‌پوشانیم.فایل app.js که توسط contextProviderمان پوشیده شده است.در نهایت، از کامپوننتی که می‌خواهیم context state را بخوانیم/به‌روزرسانی کنیم، context و هوک useContext را ایمپورت کرده و stateها و توابع را به روش زیر تخریب (destructure) می‌کنیم (و فقط از state عادی و توابع setState استفاده کنید).نمونه کامپوننت header که از useContext استفاده می‌کند.این boilerplate کمی بیشتر از پاس دادن همه چیز از روی props است، اما پس از راه اندازی بسیار قابل نگهداری‌تر، ساده‌تر و قابل درک‌تر است.نکته جالب دیگری که باید به آن اشاره کرد این است که ما می‌توانیم contextهای مختلفی را در اپلیکیشن خود داشته باشیم. ما می‌توانیم آنها را به بخش‌های مختلف تفکیک کنیم. به عنوان مثال، فرض کنید ما یکی برای stateهای احراز هویت داریم، دیگری در رابطه با تنظیمات و پیکربندی کاربر، دیگری برای پرداخت‌ها یا هر چیز دیگری... و سپس می‌توانیم آن contextها را فقط در اطراف اجزای خاصی که نیاز به استفاده از آن‌ها دارند، بپوشانیم (wrap کنیم).بنابراین اگر ما اطلاعات زیادی داریم که باید در اطراف اپلیکیشن خود به اشتراک گذاشته شود، داشتن contextهای مختلف بسیار روش ماژولارتر و مرتب‌تر برای نزدیک شدن به این موضوع خواهد بود.هوک useReducerهوک useReducer هوکی است که به ما این امکان را می‌دهد تا به صورت نیتیو reducers را در اپلیکیشن خود پیاده‌سازی کنیم تا stateهای پیچیده را مدیریت کنیم. اگر با Redux یا کتابخانه‌های مدیریت state مشابه آشنایی دارید، احتمالاً کلمه «reducer» زنگی آشنا برای شما به صدا در می‌آورد.اساسا، reducerها نوعی تابع هستند که دو یا چند آرگومان را می‌گیرند، نوعی عمل را با آن‌ها انجام می‌دهند و یک نتیجه واحد را که از دو آرگومان به دست می‌آید، برمی گرداند.یک reducer یک تابع خالص است که حالت قبلی و یک اکشن را به عنوان آرگومان می‌گیرد و حالت بعدی را برمی‌گرداند. reducer نامیده می‌شود زیرا همان نوع تابعی است که می‌توانید به آرایه ارسال کنید:Array.prototype.reduce(reducer, initialValue)اما قبل از اینکه به سراغ reducerها برویم، اگر از قبل هوک useState برای مدیریت state خود داریم، چرا به این نیاز داریم؟خب، مشکلی که ممکن است در هنگام استفاده از useState پیش بیاید این است که state جدیدی که باید تنظیم شود به state قبلی بستگی دارد یا زمانی که تغییرات state اغلب در اپلیکیشن ما اتفاق می‌افتد.در این مواقع، useState ممکن است برخی رفتارهای غیرمنتظره و غیرقابل پیش‌بینی را انجام دهد. بنابراین اینجاست که reducerها برای حل این مشکل وارد می‌شوند.هوک useReducer هوکی است که ری‌اکت ارائه می‌کند تا ما بتوانیم reducerهایی را برای مدیریت state خود پیاده‌سازی کنیم. در اینجا یک مثال پیاده‌سازی است:نمونه‌ای از مدیریت stateها با useReducerما با ایمپورت کردن هوک از ری‌اکت شروع می‌کنیم: import { useReducer } from &#x27;react&#x27;سپس یک تابع reducer را تعریف می‌کنیم، که به عنوان پارامتر state فعلی و یک اکشن برای کار بر روی آن state می‌گیرد. در داخل آن، یک دستور switch خواهد داشت که نوع اکشن را می‌خواند، اکشن مربوطه را روی state اجرا می‌کند و state به‌روز شده را برمی‌گرداند.استفاده از statements switch بر روی reducerها و حروف بزرگ برای اعلام اکشن‌ها رایج است.نمونه‌ای از یک فانکشن reducerپس از آن، زمان آن رسیده است که هوک useReducer خود را تعریف کنیم، که به نظر تقریباً شبیه به هوک useState است. ما یک مقدار را برای state خود اعلام می‌کنیم (در اینجا &#x27;state&#x27;)، تابعی که برای تغییر آن استفاده می کنیم (&#x27;dispatch&#x27;) و سپس useReducer تابع reducer را به عنوان پارامتر اول و state پیش فرض را به عنوان پارامتر دوم می‌گیرد.تعریف هوک useReducerدر نهایت، برای به‌روزرسانی state خود، مستقیماً reducer را صدا نمی‌زنیم، بلکه در عوض تابعی را که ایجاد کردیم (&#x27;dispatch&#x27;) فراخوانی می‌کنیم. به آن نوع اکشن مربوطه را که می‌خواهیم اجرا کنیم، پاس می‌دهیم. در پشت صحنه، تابع dispatch به reducer متصل می‌شود و در واقع state را تغییر می‌دهد.فراخوانی تابع dispatch این نسبت به استفاده از useState کمی بیشتر boilerplate است، اما useReducer آنقدرها هم پیچیده نیست.برای جمع بندی، فقط نیاز داریم:یک reducer، این تابعی است که تمام تغییرات state ممکن را یکپارچه می‌کند.یک تابع dispatch، که اکشن‌های اصلاحی را به reducer ارسال می‌کند.چیزی که در اینجا وجود دارد این است که عناصر UI نمی‌توانند state را مستقیماً مانند قبل در هنگام فراخوانی setState با مقدار به‌روز کنند. اکنون آن‌ها باید یک نوع اکشن را فراخوانی کنند و از طریق reducer عبور کنند، که مدیریت state را ماژولارتر و قابل پیش‌بینی‌تر می‌کند.همچنین، اگر با Redux و دیگر کتابخانه‌های مدیریت state آشنا هستید، احتمالاً متوجه شده‌اید که با Context API و هوک useReducer می‌توانیم به راحتی همان ویژگی‌هایی را که Redux ارائه می‌دهد پیاده‌سازی کنیم، اما به صورت نیتیو در ری‌اکت مدرن. بنابراین شخصاً، من فکر می‌کنم برای بیشتر موارد استفاده، شما نیازی به کتابخانه مدیریت state در کد ری‌اکت مدرن ندارید.با این حال، داستان قبلاً متفاوت بود، و احتمالاً به همین دلیل است که بسیاری از کتابخانه‌های مدیریت state محبوب شده‌اند و بسیاری از توسعه‌دهندگان هنوز هم امروزه در حال استفاده از آن‌ها هستند.هوک useRefهوک useRef تابعی است که یک آبجکت ref قابل تغییر (mutable ref object) را برمی‌گرداند که ویژگی .current آن با آرگومان ارسال شده (initialValue) مقداردهی اولیه می‌شود. شیء برگشتی برای تمام طول عمر کامپوننت باقی می‌ماند.دو کاربرد اصلی از useRef وجود دارد: پیگیری یک متغیر قابل تغییر (mutable variable) از طریق ری‌رندر، و دسترسی به گره‌های DOM یا عناصر ری‌اکت (DOM nodes or React elements).ما می‌توانیم با استفاده از هوک useRef به روش زیر یک ref را تعریف کنیم:const ref = useRef(initialValue)سپس reference.current به مقدار مرجع دسترسی پیدا می‌کند و reference.current = newValue مقدار مرجع را به‌روز می‌کند. خیلی ساده.دو نکته در مورد refها وجود دارد که باید به خاطر بسپارید:مقدار مرجع بین رندرهای مجدد کامپوننت‌ها باقی می‌ماند.به‌روز‌رسانی یک مرجع باعث ری‌رندر کامپوننت نمی‌شود.برای مشاهده مثالی از این موضوع، بیایید حالتی را تصور کنیم که در آن باید تعداد کلیک‌های روی یک دکمه را بدون ری‌رندر یک کامپوننت بشماریم. ما می‌توانیم این کار را به صورت زیر انجام دهیم:مثال استفاده از useRefبا به‌روزرسانی و ثبت ref، از ری‌رندر کامپوننت جلوگیری می‌کنیم و به هدف خود می‌رسیم. بنابراین، ۲ تفاوت اصلی بین refrence و state عبارتند از:به‌روزرسانی یک مرجع (refrence) باعث ری‌رندر نمی‌شود، در حالی که به‌روزرسانی state باعث می‌شود کامپوننت دوباره رندر شود.و همچنین... به‌روزرسانی مرجع (refrence) همزمان (synchronous) است (مقدار مرجع به روز شده فوراً در دسترس است)، در حالی که به روز رسانی state ناهمزمان (asynchronous) است (متغیر state پس از ری‌رندر به‌روز می‌شود).برخی از هوک‌های کمتر رایج اما همچنان مفیددر اینجا من دو هوک را که برای memoization در ری‌اکت استفاده می‌شود، ارائه می‌کنم. اگر با memoization آشنایی ندارید، می‌توانید به این مقاله مراجعه کنید.اساساً به خاطر سپردن (memoization) به این معنی است که کامپوننت‌ها را مجبور کنیم تا props و state را «به خاطر بسپارن»، بنابراین آن‌ها فقط وقتی که props/state تغییر کنند، ری‌رندر می‌شوند و از ری‌رندرهای غیرضروری جلوگیری می‌شود. این کار باعث افزایش پرفورمنس اپلیکیشن‌مان می‌شود.هوک useCallbackهوک useCallback توابع callbackرا که به‌عنوان props دریافت می‌کند، به خاطر می‌سپارد، بنابراین در هربار ری‌رندر، دوباره ایجاد نمی‌شوند. استفاده صحیح از useCallback می‌تواند پرفورمنس اپلیکیشن‌مان را بهبود بخشد.راهی که می‌توانیم آن را پیاده‌سازی کنیم این است که تابعی را که به‌عنوان props به یک کامپوننت فرزند در هوک useCallback بپوشانیم (wrap کنیم)، مانند این:استفاده از هوک useCallbackکاری که useCallback انجام می‌دهد این است که با وجود ری‌رندر شدن کامپوننت والد، مقدار تابع را نگه می‌دارد. این بدان معناست که تا زمانی که مقدار تابع نیز ثابت بماند، prop فرزند ثابت می‌ماند. و این مشکل ری‌رندر غیرضروری فرزند را حل می‌کند.برای استفاده از آن، فقط باید هوک useCallback را دور تابعی که تعریف می‌کنیم بپوشانیم (wrap کنیم). useCallback همچنین دارای یک آرایه وابستگی مانند useEffect است. در آرایه موجود در هوک، می‌توانیم متغیرهایی را تعریف کنیم که وقتی آن متغیر تغییر می‌کند، باعث تغییر مقدار تابع می‌شود (دقیقاً به همان روشی که useEffect کار می‌کند).نمونه‌ای از آرایه وابستگی هوک useCallbackهوک useMemoهوک useMemo یک هوک بسیار شبیه به useCallback است. اما useMemo به جای کش کردن یک تابع، مقدار بازگشتی یک تابع را کش می‌کند.در مثال زیر useMemo عدد 2 را کش می‌کند:مثالی از useMemoدر حالی که useCallback کل تابع () =&gt; num + 1 را کش می‌کند.کاستوم هوک‌های ری‌اکتیاگر در مورد آن فکر کنید، هوک‌ها فقط توابعی هستند که به ما اجازه می‌دهند منطق رایج مورد استفاده را در کامپوننت خود پیاده سازی کنیم.با پیروی از همین سلسله افکار، در اپلیکیشن‌های ری‌اکتی، استخراج قابلیت‌های پرکاربرد در توابع و اکسپورت کردن آن با نامی که با استفاده از پیشوند useشروع می‌شود، رایج است. این همان چیزی است که ما به آن کاستوم هوک می‌گوییم.بیایید نمونه‌ای از یک کاستوم هوک را ببینیم که هنگام فراخوانی، اندازه پنجره فعلی را به ما برمی‌گرداند.نمونه‌ای از کاستوم هوک به اسم useWindowSizeبعد از ساختن کاستوم هوک به شکل بالا، ما می‌توانیم کاستوم هوک‌مان را در هر کامپوننتی که می‌خواهیم به شکل زیر فراخوانی کنیم:طریقه استفاده از کاستوم هوک در یک کامپوننتهمانطور که در مثال بالا مشاهده می‌کنید، کاستوم هوک‌ها می‌توانند از هوک‌های نیتیو ری‌اکتی نیز در داخل خود استفاده کنند. اما در مورد آن‌ها فقط به عنوان توابعی فکر کنید که منطق رایج مورد استفاده مورد نیاز در بخش‌های مختلف برنامه ما را اجرا می‌کنند، واقعاً چیزی پیچیده‌تر از این نیست.اگر می‌خواهید در مورد کاستوم هوک‌ها بیشتر بدانید، در اینجا یک وب‌سایت اختصاص داده شده به این موضوع وجود دارد.جمع‌بندیخب همگی، در این مقاله نگاهی به هوک‌ها انداخته‌ایم، یکی از موضوعات اصلی و مهم در اپلیکیشن‌های ری‌اکتی. مثل همیشه امیدوارم از مقاله لذت برده باشید و چیز جدیدی یاد گرفته باشید.حتماً جهت بهبود روند نگارش و ترجمه مقالات، نظرات‌تون رو برام بنویسید.آدیوس</description>
                <category>اسنپ فود</category>
                <author>حمید کریمی</author>
                <pubDate>Tue, 24 Jan 2023 13:39:01 +0330</pubDate>
            </item>
                    <item>
                <title>درک مفهوم API Mocking: سفری که ریکوئست HTTP طی میکند.</title>
                <link>https://virgool.io/snappfood/%D8%B3%D9%81%D8%B1-%D8%B1%DB%8C%DA%A9%D9%88%D8%A6%D8%B3%D8%AA-http-qrnxaaurujdt</link>
                <description>تشبیهی از سفر ریکوئستءAPI Mocking یک تکنیک برای رهگیری ریکوئست‌های HTTP است که پاسخ به آن‌ها با جواب‌های Mock شده داده می‌شود.ما اغلب از API Mocking در حین توسعه و تست برای افزایش کنترل شبکه، و مدل سازی آن متناسب با نیازهایمان استفاده می‌کنیم و مثل خیلی چیزهای دیگر، ما بر روی لایبرری‌های third-party برای اجرای قابل اعتماد ریکوئست تکیه می‌کنیم، و API Mocking ظرفیت‌هایی برایمان فراهم می‌کند.اما تا حالا به این فکر کرده‌اید که این لایبرری‌ها چگونه کار می‌کنند؟در این سری‌های کوچک، شما و من نگاهی عمیقی به اینکه چگونه API Mockingهای مختلف کار می‌کنند و همچنین خواهیم دید که هر کدام از آن‌ها چه نقاط ضعف و قوتی دارند، و بر روی گسترش درک‌مان از ریکوئست‌های HTTP در جاوااسکریپت کار می‌کنیم.این مطلب ترجمه‌ای از Understanding API Mocking: The HTTP Request Journey است که امیدوارم بتوانم مفهوم را به خوبی برسانم و بقیه سری‌های آن را هم به محض انتشار ترجمه و منتشر کنم.مراحل API Mockingبطور خلاصه، API Mocking از دو مرحله متوالی تشکیل شده است:رهگیری یک ریکوئست HTTP ارسال شده (Intercepting an outgoing HTTP request;)پاسخ دادن به آن ریکوئست رهگیری شده با یک پاسخ mock شده.راه های زیادی برای اجرای هر یک از این ها در یک API Mock مراحل وجود دارد.برای ساختن API Mock واقعاً عالی، ما باید از تعادلی مناسب بین درستی کد و میزانی که این راه حل به ما اختیار کنترل می‌دهد مطمئن شویم؛ اما مهم‌تر از همه ما، باید بفهمیم که ریکوئست‌ها در جاوااسکریپت چگونه کار می‌کنند و همچنین تفاوت بین مراحل مختلفی که یک ریکوئست قبل از اجرا طی می‌کند، چگونه است.و مانند خیلی موارد در زندگی، ما در این سفر در مورد همه این‌ها خواهیم آموخت.سفر یک ریکوئستتمام داستان‌ها شروع خودشان را دارند، و داستان ما هم با یک ریکوئست شروع می‌شود.ببینید، رهگیری ریکوئست با نحوه انجام آن ریکوئست ارتباط تنگاتنگی دارد، اگر بخواهیم تفاوت و مبادله رویکردهای مختلف API Mocking را درک کنیم، ابتدا باید بفهمیم که چگونه ریکوئست‌های HTTP در جاوااسکریپت ساخته می‌شوند.بنابراین، مطمئن شوید که headerها بسته شده و cookieها در ظرف پر شده، ما داریم به یک سفر ریکوئست می رویم.کلاینت ریکوئست (The Request Client)هر ریکوئستی با قصد خواندن یا تغییر دیتا شروع می‌شود.ما این قصد را در کد قرار می‌دهیم و آن را برای یک request client برای اجرای آن فراهم می‌کنیم. اساساً هر APIای (native یا third-party) که به پذیرش یک درخواست و اجرای آن مربوط می‌شود، یک کلاینت ریکوئست است.برای مثال، یکی از متداول‌ترین APIهای براوزر در اجرای ریکوئست‌ها Fetch Api است:// We have an intention of fetching all movies.
// To describe that intention, we perform a &amp;quotGET&amp;quot request
// to the &amp;quot/movies&amp;quot endpoint on the server.
fetch(&#039;/movies&#039;)در عمل، ممکن است از انواع کلاینت‌های مختلف استفاده کنید، مانند Axios یا React Query؛ و انتخاب شما معمولاً بستگی به نوع ریکوئستی که می‌خواهید توصیف کنید، دارد (مثلاً ممکن است شما بخواهید از یک کلاینت مخصوص GraphQL مانند Apollo برای توصیف ریکوئست‌های GraphQL استفاده کنید).زمانی که کلاینت، ریکوئست ارسالی ما را بپذیرد، آن ابزاری برای نظارت بر اجرای آن ریکوئست به ما بر می‌گرداند، و در نهایت به ریسپانس دریافت شده از سرور رسیدگی می‌کند.مثلاً برای بحث بالا، fetch یک Promise برای حل کردن یک ریسپانس بر می‌گرداند، نمونه‌ای که می‌توانیم بخوانیم:// The fetch Promise resolves to a &amp;quotResponse&amp;quot instance
// that allows us to handle the response (e.g. get its
// status, headers, or read its body).
const response = await fetch(&#039;/movies&#039;)
console.log(response.ok, response.status)برای ما توسعه‌دهندگان، کلاینت ریکوئست معمولاً جایی است که تعامل ما با ریکوئست به پایان می‌رسد؛ اما برای خود ریکوئست، این تازه شروع ماجراست.در حالی که کلاینت‌های ریکوئست برای ما یک راه عالی برای اجرا و مدیریت آسان‌تر ریکوئست‌ها فراهم می‌کنند، آن‌ها فقط انتزاعی (abstractions) برای کد زیربنایی (underlying code) هستند که تمام کارهای سنگین را انجام می‌دهند.و این دقیقاً همان جایی است که ریکوئست ما به آن جا می‌رود.محیط (The Environment)بدون توجه به کلاینت ریکوئست، ریکوئست ما ناگزیر به API استاندارد محیط مسئول رسیدگی به ریکوئست‌های HTTP می‌رسد.هنگام استفاده از کلاینت ریکوئست third-party، آن تعامل را به کلاینت محول می‌کنیم، در حالی که ممکن است مستقیماً با آن API استاندارد تعامل داشته باشیم، و بنابراین ساخت و رسیدگی یک ریکوئست به جزئیات پیاده‌سازی کلاینت ریکوئست تبدیل می‌شود؛ برای مثال، وقتی از Axios استفاده می‌کنیم، ریکوئست ما را به عنوان XMLHttpRequest در براوزر و http.ClientRequest در Node.js نمایش می‌دهد، بدون آنکه ما حتی متوجه شویم.اما ما امروز اینجا هستیم تا فراتر از انتزاع های third-party برویم و در مورد آن APIهای محیطی یاد بگیریم، اینطور نیست؟مهم است در نظر داشته باشید که هر محیطی، ماژول شبکه خود را متفاوت پیاده‌سازی می‌کند. ما به عنوان مهندسان جاوااسکریپت بیشتر به محیط‌های براوزر و Node.js علاقه داریم.بیایید نگاهی بیندازیم که چه native APIهایی برای ارائه ریکوئست وجود دارد.مرورگر (Browser)window.fetchءFetch Api یکی از رایج‌ترین راه‌ها برای درخواست در وب است.در سال ۲۰۱۵ به جهان معرفی شد و به عنوان گامی رو به جلو از XMLHttpRequestراه اندازی شد، و بدون شک زندگی ما توسعه‌دهندگان را برای بهتر شدن تغییر داد.fetch(&#039;https://api.example.com/users&#039;, {
   method: &#039;POST&#039;,
   headers: { &#039;Content-Type&#039;: &#039;application/json&#039; },
   body: JSON.stringify({ name: &#039;Alice&#039; })
})پیاده‌سازی براوزر برای Fetch در کد native C است و فراخوانی window.fetch() آخرین سطحی‌ است که می‌توانیم با آن تعامل داشته باشیم.window.XMLHttpRequestءXMLHttpRequest اولین حضور عمومی خود به عنوان یک API Fully-functional برای ارسال ریکوئست‌ها را در سال ۲۰۰۲ داشت.این ممکن است برای برخی غافل گیرکننده باشد، اما XHR هنوز هم در براوزرها تا به امروز ارسال می‌شود و یک راه بر حق برای ساختن ریکوئست‌هاست! بیش از این، XHR چند قابلیت را به نمایش می‌گذارد که حتی Fetch مدرن هم آن‌ها را ندارد، مانند مانیتور کردن فرآیند یک ریکوئست و کنسل شدن ریکوئست، که قبل از تبدیل شدن AbortControllerبه یک چیز، از طریق Fetch امکان پذیر نبود.const request = new XMLHttpRequest()
request.open(&#039;POST&#039;, &#039;https://api.example.com/users&#039;)
request.setRequestHeader(&#039;Content-Type&#039;, &#039;application/json&#039;)
request.write(JSON.stringify({ name: &#039;Alice&#039; })
request.send()شبیه بهwindow.fetch،ریشه‌های XMLHttpRequest نیز به عمق کد native browser بدون هیچ لایه میانی می‌روند تا منطق mocking ما را اتصال دهند.Node.jshttp.request (https.request)ء Node.js برای ما یک API سطح بالا برای انجام ریکوئست‌ها از طریق ماژول‌های httpو httpsفراهم کرده است؛ در حالی که آن‌ها متدهای مشابهی را به اشتراک می‌گذارند، مانند .get()و .request()، اما پیاده‌سازی آن‌ها متفاوت است؛ زیرا ریکوئست پروتکل‌های متفاوتی را مدیریت می‌کنند.import https from &#039;https&#039;
const request = https.request(&#039;https://api.example.com/users&#039;, {
     method: &#039;POST&#039;,
     headers: { &#039;Content-Type&#039;: &#039;application/json&#039; }
})
request.write(JSON.stringify({ name: &#039;Alice&#039; }))
request.end()ء API http.request()چیزی است که اکثر کلاینت ریکوئست‌ها در Node.js به صورت داخلی از آن استفاده می‌کنند.شاید گفتن اینکه APIای که باعث تولد خیلی از کلاینت ریکوئست‌ها در آن محیط شده همین API است، خیلی پر حرفی باشد (فرض وحشیانه من در اینجا).http.ClientRequestحرکت بیشتر به سمت عمق call stack، ءhttp.request ریکوئست‌ها را با استفاده از کلاس http.ClientRequestنشان می دهد (و رسیدگی می کند).منصفانه است ذکر شود  که برخی از لایبرری‌ها و polyfillها مستقیماً از این کلاس استفاده می‌کنند و به طور کلی API سطح بالاتر را دور می‌زنند.همانطور که گفته شد، ساخت یک ریکوئست از طریق http.ClientRequestشبیه به استفاده از http.requestباشد، و حتی ممکن است گاهی اوقات این تفاوت، با چشم غیر مسلح قابل مشاهده نباشد:import http from &#039;http&#039;
import https from &#039;https&#039;
const req = new http.ClientRequest({
     protocol: &#039;https:&#039;,
     host: &#039;api.example.com&#039;,
     pathname: &#039;/users&#039;,
     headers: {
        &#039;Content-Type&#039;: &#039;application/json&#039;,
     },
     agent: new https.Agent(),
})
req.write(JSON.stringify({ name: &#039;Alice&#039; }))
req.end()نکته آنکه این همان کلاس http.ClientRequestاست که هر دو ریکوئست HTTP و HTTPS را توصیف می‌کند. برخلاف تمایز http.requestو https.requestدر سطح بالاتر.net.Socketحتی عمیق‌تر برویم. هر ریکوئست HTTP لزوماً داده‌های منتقل شده از طریق یک سوکت هستند و Node.js هم یک کلاس net.Socket برای توصیف آن دارد.import { Socket } from &#039;net&#039;
const socket = new Socket()
socket.connect(443, &#039;api.example.com&#039;, () =&gt; {
     socket.write(&#039;POST /users HTTP/1.0\n&#039;)
     socket.write(&#039;Content-Type: application/json\n&#039;)
     socket.end(JSON.stringify({ name: &#039;Alice&#039; }))
})این واقعیت که ما پیام‌های HTTP خام را از طریق سیم ارسال می‌کنیم، باید تصور خوبی از سطح پایین Socket API به شما بدهد.هر چند بعید است که مستقیماً از این API استفاده کنید، اما همچنان بخشی اجتناب ناپذیر از سفر ریکوئست در Node.js است و در نتیجه برای انتخاب ما از رویکرد API Mocking مهم است.تذکرات مفیددر Node.js نسخه 17 fetchAPI مشابه با آنچه که در براوزر وجود دارد، اضافه شده.از آن جایی که آن‌ها با مشخصات یکسانی مطابقت دارند، fetchدر Node.js به ترتیب ریکوئست‌ها و ریسپانس‌ها را با استفاده از کلاس‌های Requestو Responseنشان می‌دهد، اما آن‌ها همچنان به‌ عنوان انتزاع بر روی APIهای سطح پایینی که در بالا به آن اشاره کردیم، عمل می‌کنند.هنگامی که ماژول شبکه کار خود را انجام داد، در نهایت ریکوئست انجام می‌شود و محیط را ترک می کند و از فیبر به سمت سرور درخواست شده حرکت می‌کند.سرورسرور جایی است که ریکوئست‌ها برای حل و فصل نهایی ارسال می‌شوند.سرور دورترین منطقه از ارسال ریکوئست ما است؛ زیرا محیطی متفاوت است که اغلب به زبانی متفاوت از برنامه ما پیاده‌سازی می‌شود و پیچیدگی‌های خودش را دارد. هر چند هنگامی که سرور ریکوئست را حل کرد، ریسپانس را از طریق همان سفر ارسال می‌کند تا در نهایت به کلاینت ریکوئست بازگردد.بنابراین، هنگامی که ریکوئست ما به سرور می‌رسد، ما نمی‌توانیم کاری انجام دهیم تا از زمان اجرای سمت کلاینت بر آن ریکوئست تأثیر بگذاریم.جمع بندیهدف هر سفر بهبود و تغییر کسانی است که به اندازه کافی شجاع هستند که وارد آن شوند.و سفر ریکوئستی که ما به تازگی پشت سر گذاشتیم نیز از این قاعده مستثنی نیست. همانطور که در مورد روش‌های مختلف توصیف ریکوئست‌ها و نقاط بازرسی هر ریکوئست آموختیم، می‌توانیم پیش‌نویس راه‌های ممکن برای اجرای API Mocking در برنامه‌مان را ادامه دهیم.این دقیقاً همان چیزی است که در پست بعدی به آن خواهم پرداخت.ممنون از وقتی که گذاشتین و این مطلب رو مطالعه کردین.منتظر نظرات و پیشنهادات شما هستم تا بتونم بر روی مطالب بعدی بهتر کار کنم.</description>
                <category>اسنپ فود</category>
                <author>حمید کریمی</author>
                <pubDate>Tue, 20 Dec 2022 13:19:37 +0330</pubDate>
            </item>
                    <item>
                <title>بیشترین سوالات پرسیده شده از تایپ اسکریپت در stackoverflow و پاسخ آن‌ها - قسمت اول</title>
                <link>https://virgool.io/snappfood/%D8%AA%D8%A7%DB%8C%D9%BE-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-type-%DB%8C%D8%A7-interface-%D8%B3%D9%88%D8%A7%D9%84%D8%A7%D8%AA-%D9%85%D8%AA%D8%AF%D8%A7%D9%88%D9%84-%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-uxp3yottkp45</link>
                <description>تا حالا هیچ دولوپری نگفته «من از stackoverflow متنفرم»در حالی که شما تنها یک سرچ گوگل با پیدا کردن جواب فاصله دارید، حقیقتاً درک درست راه حل برای شما مهم‌ترین بخش است.در این سری مقالات می‌خواهیم ۷ سوال پر تکرار در stackoverflow درباره تایپ‌اسکریپت را بررسی کنیم.این سری مقالات ترجمه‌ی این مقاله است، و اولین تجربه‌ی من در ترجمه، پس اگر با مشکلاتی مواجه است، لطفاً‌ در بخش نظرات اعلام کنید، تا من هم بتوانم مقالات بعدی را بهتر ترجمه کنم.با این مقالات امیدوارم که به درک عمیق‌تری از مسائلی که ممکن است با تایپ‌اسکریپت مواجه شوید، برسید.اگر به تازگی شروع به یادگیری تایپ‌اسکریپت کرده‌اید، این موضوع نیز مرتبط است و چه راهی بهتر از آشنایی با چالش های آینده خود!چه تفاوتی بین Interfaces و Types در تایپ‌اسکریپت وجود دارد؟تفاوت interfaces و types در تایپ‌اسکریپتدرواقع Interface و Type که نوع تایپی هستند، یک رقابت تنگاتنگی باهم دارند.وقتی که شروع به یادگیری تایپ‌اسکریپت می‌کنید، ممکن است انتخاب بین این دو برای شما مشکل و گیج کننده باشد. این مقاله سردرگمی شما را برطرف خواهد کرد و به شما کمک می‌کند تا انتخاب مناسبی داشته باشید.در نمونه‌های زیادی، شما می‌توانید Interface و یا Type را بجای یکدیگر استفاده کنید.تقریباً تمام فیچرهای Interface در type نیز در دسترس است، بجز اینکه شما نمی‌توانید پراپرتی جدیدی در Type با استفاده از re-declaring اضافه کنید. شما حتماً باید یک intersection type استفاده کنید.چرا از همان ابتدا درباره Type و Interface گیج می‌شویم؟هر زمان که ما با گزینه‌های متعددی برای انتخاب مواجه می‌شویم، اکثر مردم از تضاد انتخاب رنج می‌برند.اما خوشبختانه در این مورد خاص، فقط دو گزینه وجود دارد.نکته‌ی اصلی گیج کننده در اینجا و بین این دو گزینه این است که در اکثر موارد به طور مساوی شبیه به هم هستند و تطابق دارند.و این کار را برای یک انتخاب مشخص سخت می‌کند، مخصوصاً وقتی که تازه شروع به کار با تایپ‌اسکریپت می‌کنید.یک مثال ساده از Type و Interfaceتعریف کردن یک تایپ Human را در نظر بگیرید:// type 
type Human = {
  name: string 
  legs: number
  head: number
}
// interface 
interface Human {
   name: string 
   legs: number 
   head: number
}هر دو روش برای تعریف تایپ‌ Human با استفاده از Type و Interface درست است.تفاوت‌های بین Type و Interfaceتفاوت کلیدی: Interface فقط می‌تواند شکل آبجکت (object shape) را توصیف کند. اما Type برای تایپ‌های دیگر مانند primitives, unions و tuplesها می‌تواند استفاده شود.تعریف متغیر با Type در انواع داده‌هایی که می‌توانید نمایش دهید کاملاً انعطاف‌پذیر است. از primitiveهای اولیه unionهای پیچیده و tuplesها، همانطور که در بخش زیر نشان داده شده است:// primitives
type Name = string
// object
type Male = {
   name: string
}
type Female = {
    name: string
}
// union
type HumanSex = Male | Female
// tuple
type Children = [Female, Male, Female]بر خلاف Type، شما برای تعریف تایپ‌های یک آبجکت فقط باید از Interface استفاده کنید.تفاوت کلیدی:‌ یک Interface را می‌توان با چندین بار اعلام (declare) آن گسترش داد.مثال زیر را در نظر بگیرید:interface Human {
   name: string 
}
interface Human {
    legs: number
}دو اعلام (declaration) بالا، به شکل زیر تغییر می‌تواند باشد:interface Human {
    name: string 
    legs: number 
}در اینجا Human را می‌توان با یک interface تعریف کرد: ترکیبی از اعضای هر دو اعلامپراپرتی legs برای آبجکت Human الزامی است.مشاهده در Typescript Playgroundدر صورتی که همچین مدل تعریف کردن در Type امکان‌پذیر نیست و باعث بوجود آمدن پیغام خطا می‌شود.type Human = {
    name: string
}
type Human =  {
     legs: number 
}
const h: Human = {
     name: &#039;gg&#039;,
     legs: 5 
}  آبجکت Human دوبار تعریف شده استمشاهده در Typescript Playgroundبرای نوشتن همچین چیزی با استفاده از Type، باید آن‌ها را بهم متصل کنیم:type HumanWithName = {
    name: string 
}
type HumanWithLegs =  {
    legs: number 
}
type Human  = HumanWithName &amp; HumanWithLegs
const h: Human = {
   name: &#039;gg&#039;,
   legs: 5 
}  مشاهده در Typescript Playgroundتفاوت جزئی: هردو Type و Interface قابلیت تعمیم (extend) دارند، اما با syntaxهای متفاوتبا Interface شما باید از کلمه کلیدی extends استفاده کنید. اما برای Type، شما باید از یک اتصال دهنده استفاده کنید.به مثال‌های زیر توجه کنید:تعمیم دادن یک Type با Typeای دیگرtype HumanWithName = {
  name: string 
}
type Human = HumanWithName &amp; {
   legs: number 
   eyes: number 
}تعمیم دادن یک Type با Interfaceinterface HumanWithName {
  name: string 
}
type Human = HumanWithName &amp; {
   legs: number 
   eyes: number 
}تعمیم دادن یک Interface با Interfaceinterface HumanWithName {
  name: string
}
interface Human extends HumanWithName {
  legs: number 
  eyes: number 
}تعمیم دادن یک Interface با یک Typetype HumanWithName = {
  name: string
}
interface Human extends HumanWithName {
  legs: number 
  eyes: number 
}همانطور که در مثال‌های بالا مشاهده می‌کنید، هیچ دلیل منحصر به فردی برای ترجیح دادن یکی به دیگری وجود ندارد. هرچند که syntaxهای آن‌ها متفاوت است.تفاوت جزئی: کلاس‌ها فقط می‌توانند اعضای شناخته شده را به صورت استاتیک پیاده سازی کنند.یک کلاس می‌تواند Interface و یا Type را پیاده‌سازی کند. هرچند که یک کلاس نمی‌تواند یک تایپ union را پیاده‌سازی و یا گسترش دهد.به مثال‌های زیر توجه کنید:پیاده‌سازی کلاس با Interfaceinterface Human {
  name: string
  legs: number 
  eyes: number 
}
class FourLeggedHuman implements Human {
  name = &#039;Krizuga&#039;
  legs = 4
  eyes = 2
}پیاده‌سازی کلاس با Typetype Human = {
  name: string
  legs: number 
  eyes: number 
}
class FourLeggedHuman implements Human {
  name = &#039;Krizuga&#039;
  legs = 4
  eyes = 2
}هردوی این‌ها به خوبی و بدون خطا کار می‌کنند، هرچند در مثال زیر به خطا میخورد:پیاده سازی کلاس با uniontype Human = {
     name: string
} | {
    legs: number
    eyes: number
}
class FourLeggedHuman implements Human {
    name = &#039;Krizuga&#039;
    legs = 4
    eyes = 2
}A class can only implement an object type or intersection of object types with statically known members. مشاهده در Typescript Playgroundجمع‌بندی Type در مقابل Interfaceبرداشت شما ممکن است متفاوت باشد، اما هرجا که ممکن است، من به Type چسبیده‌ام، بخاطر انعطاف‌پذیری و syntax ساده‌ای که دارد. همین، من Type را انتخاب می‌کنم، بجز هرجای بخصوصی که به Interface بخاطر خاصیت‌هایش نیاز داشته باشم.برای بیشتر قسمت‌ها، همینطور شما‌ می‌توانید بر اساس ترجیح شخصی‌تان تصمیم بگیرید، اما باید بر انتخاب‌تان استوار باشید، حداقل بر روی یک پروژه.برای کامل شدن، من باید مقایسه پرفورمنس بین Type و Interface را اضافه کنم، تا ببینیم کدام سریع‌تر است. هرچند این به عنوان یک مشکل برای من باقی مانده است.عناوین مقاله‌های آیندهIn TypeScript, what is the ! (exclamation mark / bang) operator?What is a “.d.ts” file in TypeScript?How Do You Explicitly Set a New Property on ‘window’ in TypeScript?Are Strongly Typed Functions as Parameters Possible in TypeScript?How to Fix Could Not Find Declaration File for Module …?How Do I Dynamically Assign Properties to an Object in TypeScript?ممنون از وقتی که برای مطالعه گذاشتید، حتماً نظر خودتون رو درباره موضوع، ترجمه و نگارش بهم بگید تا بتونم روی مطالب بعدی بهتر کار کنم و کیفیت‌شون رو افزایش بدم.</description>
                <category>اسنپ فود</category>
                <author>حمید کریمی</author>
                <pubDate>Fri, 15 Jul 2022 13:07:40 +0430</pubDate>
            </item>
            </channel>
</rss>