امیدوارم حالتون خوب باشه دوستان.
داخل آپدیت ES2025 یک static method جدید برای به اسم Promise.try اضافه شده و در این پست باهم برسیش میکنیم.
https://telegra.ph/%D9%85%D8%AA%D8%AF-%D8%AC%D8%AF%DB%8C%D8%AF-Promisetry-%D8%AF%D8%B1-ES2025-07-21
البته به صورت تستی با استفاده از telegra.ph شاید بهتر باشه
داخل آپدیت ES2025 یک static method جدید برای به اسم Promise.try اضافه شده و در این پست باهم برسیش میکنیم.
https://telegra.ph/%D9%85%D8%AA%D8%AF-%D8%AC%D8%AF%DB%8C%D8%AF-Promisetry-%D8%AF%D8%B1-ES2025-07-21
البته به صورت تستی با استفاده از telegra.ph شاید بهتر باشه
Telegraph
متد جدید Promise.try در ES2025
NodeMaster درود امیدوارم حالتون باشه. داشتم آپدیت مربوط به ES2025 رو نگاهی یک چیز جالب دیدم. تصور کنید همچین کدی دارید function error() { throw new Error("MY ERROR") } function promiseAdaptor(callback) { return Promise.resolve(callback()) } promi…
👍13
درود دوستان.
قبلا که #python کد میزدم یک پکیج داشت به اسم isort که import ها رو خیلی تر تمیز sort میکرد. همیشه دنبال یک پکیج خوب بودم برای #typenoscript که همچین کاری رو انجام بده تا بلاخره دیروز یک پکیح خوب پیدا کردم که میتونید به عنوان config prettier استفاده کنید.
البته package های دیگ هم هستن ولی این خیلی برای من راحت تر بود. فکر کنم eslint هم همچین چیزی داشته باشه ولی فرصت نشده تست کنم.
https://www.npmjs.com/package/prettier-plugin-organize-imports
قبلا که #python کد میزدم یک پکیج داشت به اسم isort که import ها رو خیلی تر تمیز sort میکرد. همیشه دنبال یک پکیج خوب بودم برای #typenoscript که همچین کاری رو انجام بده تا بلاخره دیروز یک پکیح خوب پیدا کردم که میتونید به عنوان config prettier استفاده کنید.
البته package های دیگ هم هستن ولی این خیلی برای من راحت تر بود. فکر کنم eslint هم همچین چیزی داشته باشه ولی فرصت نشده تست کنم.
https://www.npmjs.com/package/prettier-plugin-organize-imports
👍7
Forwarded from amir jahan
Node.js Backend Developer
📍 مکان: تهران – با امکان دورکاری کامل یا هیبریدی
👨💻 نوع همکاری: تماموقت یا پارهوقت (ساعت کاری منعطف، مبتنی بر خروجی)
درباره ما
ما یک تیم تحقیق و توسعهی پویا هستیم که روی ساخت محصولات دیجیتال نوآورانه با محوریت هوش مصنوعی، دادهکاوی و سرویسهای کاربردی وب کار میکنیم. تمرکز ما روی طراحی و پیادهسازی معماریهای تمیز، مقیاسپذیر و انعطافپذیر برای پروژههاییست که کاربران واقعی و چالشهای فنی جدی دارند.
در حال حاضر به دنبال یک توسعهدهندهی بکاند با Node.js هستیم که عاشق حل مسئله و طراحی سیستمهای پایدار باشه و بتونه در ساخت سرویسهای مقیاسپذیر و حرفهای نقش کلیدی ایفا کنه.
مسئولیتها
طراحی و توسعهی سرویسهای بکاند با استفاده از Node.js (ترجیحاً با Nest.js یا Express.js)
طراحی و پیادهسازی APIها (RESTful / GraphQL) با رعایت اصول امنیتی و بهینهسازی
اتصال به دیتابیسهای MongoDB و PostgreSQL و طراحی مدل دادهی کارآمد
پیادهسازی صفهای پردازش با Kafka یا RabbitMQ
استفاده از Redis برای کشینگ و بهبود عملکرد سیستم
مشارکت در طراحی معماری سیستمها بر اساس Clean Architecture و Design Patterns
همکاری در Code Review و بهبود کیفیت کد تیم
مستندسازی مؤثر برای ماژولها و سرویسها
مهارتها و تجربهها
تسلط بالا به Node.js و یکی از فریمورکهای محبوب (Nest.js یا Express.js)
تجربه کار عملی با MongoDB و PostgreSQL
آشنایی با ابزارهای Messaging Queue مثل Kafka یا RabbitMQ
تجربهی استفاده از Redis برای کش و مدیریت Session
آشنایی با مفاهیم Microservices و معماریهای رویدادمحور (Event-driven)
تسلط به Git و آشنایی با ابزارهای مدیریت پروژه (Jira یا مشابه)
توانایی تستنویسی (Unit/Integration)
درک مفاهیم امنیتی وب و استانداردهای OWASP
آشنایی با CI/CD و مفاهیم DevOps امتیاز محسوب میشود
چرا اینجا جذابه؟
تیم حرفهای ولی صمیمی داریم
محیط کاری آزمایشی + تحقیقاتی، مناسب عاشقان یادگیری
امکان دورکاری کامل یا حضور در دفتر (اگر تهران باشی)
ساعت کاری شناور؛ تمرکز ما روی نتیجهست، نه زمان
درگیر پروژهای میشی که کاربر واقعی، مقیاسپذیری و چالشهای معماری جدی داره
اگر این موقعیت برات جالبه، لطفاً برامون بفرست:
رزومه (حتی اگر خیلی رسمی نیست)
لینک گیتهاب یا چندتا از پروژههای قبلیت
حقوق پیشنهادی (اختیاری)
مدت زمانی که میتونی در هفته همکاری داشته باشی
@amirjaha_n
y2311769@gmail.com
📍 مکان: تهران – با امکان دورکاری کامل یا هیبریدی
👨💻 نوع همکاری: تماموقت یا پارهوقت (ساعت کاری منعطف، مبتنی بر خروجی)
درباره ما
ما یک تیم تحقیق و توسعهی پویا هستیم که روی ساخت محصولات دیجیتال نوآورانه با محوریت هوش مصنوعی، دادهکاوی و سرویسهای کاربردی وب کار میکنیم. تمرکز ما روی طراحی و پیادهسازی معماریهای تمیز، مقیاسپذیر و انعطافپذیر برای پروژههاییست که کاربران واقعی و چالشهای فنی جدی دارند.
در حال حاضر به دنبال یک توسعهدهندهی بکاند با Node.js هستیم که عاشق حل مسئله و طراحی سیستمهای پایدار باشه و بتونه در ساخت سرویسهای مقیاسپذیر و حرفهای نقش کلیدی ایفا کنه.
مسئولیتها
طراحی و توسعهی سرویسهای بکاند با استفاده از Node.js (ترجیحاً با Nest.js یا Express.js)
طراحی و پیادهسازی APIها (RESTful / GraphQL) با رعایت اصول امنیتی و بهینهسازی
اتصال به دیتابیسهای MongoDB و PostgreSQL و طراحی مدل دادهی کارآمد
پیادهسازی صفهای پردازش با Kafka یا RabbitMQ
استفاده از Redis برای کشینگ و بهبود عملکرد سیستم
مشارکت در طراحی معماری سیستمها بر اساس Clean Architecture و Design Patterns
همکاری در Code Review و بهبود کیفیت کد تیم
مستندسازی مؤثر برای ماژولها و سرویسها
مهارتها و تجربهها
تسلط بالا به Node.js و یکی از فریمورکهای محبوب (Nest.js یا Express.js)
تجربه کار عملی با MongoDB و PostgreSQL
آشنایی با ابزارهای Messaging Queue مثل Kafka یا RabbitMQ
تجربهی استفاده از Redis برای کش و مدیریت Session
آشنایی با مفاهیم Microservices و معماریهای رویدادمحور (Event-driven)
تسلط به Git و آشنایی با ابزارهای مدیریت پروژه (Jira یا مشابه)
توانایی تستنویسی (Unit/Integration)
درک مفاهیم امنیتی وب و استانداردهای OWASP
آشنایی با CI/CD و مفاهیم DevOps امتیاز محسوب میشود
چرا اینجا جذابه؟
تیم حرفهای ولی صمیمی داریم
محیط کاری آزمایشی + تحقیقاتی، مناسب عاشقان یادگیری
امکان دورکاری کامل یا حضور در دفتر (اگر تهران باشی)
ساعت کاری شناور؛ تمرکز ما روی نتیجهست، نه زمان
درگیر پروژهای میشی که کاربر واقعی، مقیاسپذیری و چالشهای معماری جدی داره
اگر این موقعیت برات جالبه، لطفاً برامون بفرست:
رزومه (حتی اگر خیلی رسمی نیست)
لینک گیتهاب یا چندتا از پروژههای قبلیت
حقوق پیشنهادی (اختیاری)
مدت زمانی که میتونی در هفته همکاری داشته باشی
@amirjaha_n
y2311769@gmail.com
سلام و درود دوستان امیدوارم حالتون خوب باشه.
یک نکته ای که همیشه در پروژه ها میبینم چه در پروژه های Front و چه در پروژه های Backend وقتی با یک HTTP Request کار میکنیم اکثرا URL ها رو به صورت Hardcode میبینیم و اگر پارامتری هم نیاز داشته باشه در نهایت با استفاده از #JavaScript Template Literal کارمون رو پیش میبریم.
به صورت کلی استفاده کردن از Template Literal هیچ مشکلی نداره و کارمون راه میندازه ولی گاهی اوقات ممکنه کمی برامون دردسر ایجاد کنه. برای درک این موضوع به مثال زیر توجه کنید.
در اینجا همه چی اوکی کار میکنه مشکلی نیست ولی یک نکته که باید توجه کنیم این هست که حتما BASE_URL ما "/" اضافه نداشته باشد.
به صورت کلی مسئله خیلی بزرگی نیست ولی همین نکته کوچیک داخل code base که بهش آشنایی ندارید ممکنه ساعت ها ازتون زمان بگیره تا پیداش کنیم. خب حالا سوال پیش میاد که راه حل برای این موضوع چی هست؟
برای حل این موضوع میتونید از URL Web API استفاده کنید. به عنوان مثال اگر کد بالا را بخواهیم Refactor کنیم به این صورت خیلی کارمون تمیز تر و راحت تر میشه و دیگه همچین چیزی رو نمیبینیم.
باتوجه به این که داریم از Web API استفاده میکنیم داخل تمامی Runtime ها به راحتی میتونیم از این API استفاده کنیم و همشون هم به همین شکل کار میکنن.
حالا گاهی اوقات میخوایم querystring مثل زیر داشته باشیم
دوباره استفاده از Template literal هیچ ایرادی نداره کارمون راه میندازه ولی اگر بخواهیم این رو هم تمیز تر کنیم که در آینده کارمون راحت تر باشه و کد تمیز تری داشته باشیم چطور؟
برای این کار هم میتونیم از سه روش کارمون رو پیش ببریم
1. استفاده از node:querystring که این module فقط استاندارد #NodeJS هست.
2. استفاده از URLSearchParams Web API که باتوجه به این که Web API هست قطعا همه جا پشتیبانی میشه.
3. استفاده از راه حل دوم به صورت غیر مستقیم با استفاده از searchParams property مربوط به URL.
حالا اگر بخواهیم مثال بالا رو Refactor کنیم و همچین چیزی رو اضاف کنیم به این صورت عمل میکنیم.
در نگاه اول ممکنه خیلی نکته بزرگی به نظر نیاد ولی داخل code base های بزرگ که با کلی API 3rd party کار میکنید میتونه فرشته نجات باشه.
یک نکته ای که همیشه در پروژه ها میبینم چه در پروژه های Front و چه در پروژه های Backend وقتی با یک HTTP Request کار میکنیم اکثرا URL ها رو به صورت Hardcode میبینیم و اگر پارامتری هم نیاز داشته باشه در نهایت با استفاده از #JavaScript Template Literal کارمون رو پیش میبریم.
به صورت کلی استفاده کردن از Template Literal هیچ مشکلی نداره و کارمون راه میندازه ولی گاهی اوقات ممکنه کمی برامون دردسر ایجاد کنه. برای درک این موضوع به مثال زیر توجه کنید.
import process from "node:process";
const BASE_URL = process.env.BASE_URL;
const url = `${BASE_URL}/posts/1`;
fetch(url);
در اینجا همه چی اوکی کار میکنه مشکلی نیست ولی یک نکته که باید توجه کنیم این هست که حتما BASE_URL ما "/" اضافه نداشته باشد.
https://jsonplaceholder.typicode.com/ ❌
https://jsonplaceholder.typicode.com ✅
به صورت کلی مسئله خیلی بزرگی نیست ولی همین نکته کوچیک داخل code base که بهش آشنایی ندارید ممکنه ساعت ها ازتون زمان بگیره تا پیداش کنیم. خب حالا سوال پیش میاد که راه حل برای این موضوع چی هست؟
برای حل این موضوع میتونید از URL Web API استفاده کنید. به عنوان مثال اگر کد بالا را بخواهیم Refactor کنیم به این صورت خیلی کارمون تمیز تر و راحت تر میشه و دیگه همچین چیزی رو نمیبینیم.
import process from "node:process";
import { URL } from "node:url";
const url = new URL(process.env.BASE_URL);
const path = "/posts/1";
url.pathname = path;
fetch(url.href);
باتوجه به این که داریم از Web API استفاده میکنیم داخل تمامی Runtime ها به راحتی میتونیم از این API استفاده کنیم و همشون هم به همین شکل کار میکنن.
حالا گاهی اوقات میخوایم querystring مثل زیر داشته باشیم
/post?userId=1&tag=nodejs
دوباره استفاده از Template literal هیچ ایرادی نداره کارمون راه میندازه ولی اگر بخواهیم این رو هم تمیز تر کنیم که در آینده کارمون راحت تر باشه و کد تمیز تری داشته باشیم چطور؟
برای این کار هم میتونیم از سه روش کارمون رو پیش ببریم
1. استفاده از node:querystring که این module فقط استاندارد #NodeJS هست.
2. استفاده از URLSearchParams Web API که باتوجه به این که Web API هست قطعا همه جا پشتیبانی میشه.
3. استفاده از راه حل دوم به صورت غیر مستقیم با استفاده از searchParams property مربوط به URL.
حالا اگر بخواهیم مثال بالا رو Refactor کنیم و همچین چیزی رو اضاف کنیم به این صورت عمل میکنیم.
import process from "node:process";
import { URL } from "node:url";
import querystring from "node:querystring";
const url = new URL(process.env.BASE_URL);
const query = { userId: 1, tag: "NodeMaster" };
// #1 Using querystring module from NodeJS
const path = "/posts";
url.pathname = path;
url.search = querystring.stringify(query);
// #2 Using URLSearchParams
url.pathname = "/posts";
url.search = new URLSearchParams(query).toString();
// #3 Using searchParams property of URL instance
url.pathname = "/posts";
url.searchParams.append("userId", "1");
url.searchParams.append("tag", "NodeMaster");
//
fetch(url.href);
در نگاه اول ممکنه خیلی نکته بزرگی به نظر نیاد ولی داخل code base های بزرگ که با کلی API 3rd party کار میکنید میتونه فرشته نجات باشه.
👍17
درود دوستان امیدوارم حالتون خوب باشه. یک ویژگی خیلی کوچیک #Python داشت که من همیشه دلم میخواد داخل #NodeJS ببینم. این ویژگی خیلی وقته روی #Deno هست ( فکر کنم #BunJS هم داره ). واقعا جای خالیش رو من حس میکردم. و بلاخره این ویژگی رو به صورت Experimental در آپدیت 22.18 دیدیم که اضافه شد. برا این که وارد بحث بشیم دوست دارم با این کد پایتون شروع کنم.
توضیح کد خیلی ساده هست که با استفاده از این پترن میشه تشخیص داد آیا این بخش از code که داره اجرا میشه آیا import شده توسط یک ماژول دیگه یا ماژول اصلی هست که باهاش برنامه رو اجرا کردن؟ اگر ماژول اصلی باشه که برنامه رو run کردن فانکشن main رو اجرا میکنه برنامه وارد main routine خودش میشه. شاید فکر کنید داخل زبانی مثل #Python و #JavaScript اینکار احمقانه باشه باتوجه به این که هر expressionـی رو میتونیم داخل top level خودمون اجرا کنیم. پس مزیت این کار چیه؟ جواب این هست که باتوجه به این که ما برنامه رو مینویسیم خب ما میدونیم کجا main routine رو اجرا کنیم ولی تصور کنید روی یک code base بزرگ رفتین و دنبال entrypoint میگردید. در این سناریو میتونه به عنوان داکیومنتیشن مناسب باشه. یا زمانی بخواید کدی رو اجرا کنید که فقط و فقط اگر کسی اون ماژول رو import کرده باشه و ... . همین الان هم وقتی پروژه #NestJS دارید bootstrap function دقیقا داره نقش main routine رو بازی میکنه و شما حتما باید اون رو اجرا کنید که برنامتون اجرا بشه. معمولا داخل #NestJS همچین چیزی میبینیم
سناریویی رو در نظر بگیرد به هر دلیلی میخواید از این main.js یک چیزی رو import کنید( هرچند اگر همچین چیزی نیاز داشتید بهتره سعی کنید راه دیگه ای پیدا کنید ) و اگر شما این فایل رو import کنید داخل یک ماژول دیگه خب bootstrap اجرا میشه و ما این رو نمیخوایم. پس چیکار میتونیم کنیم؟
اینجا هست import.meta.main به کمک ما میاد حالا اگر شما مستقیما node main.js بزنید فانکشن bootstrap اجرا میشه ولی اگر از یک فایل دیگ مثل server.js داشته باشید و این فایل رو import کنید بخش else اجرا میشه و bootstrap هیچ وقت call نمیشه.
def main():
print("Hello From Main Function")
if __name__ == "__main__":
main()
توضیح کد خیلی ساده هست که با استفاده از این پترن میشه تشخیص داد آیا این بخش از code که داره اجرا میشه آیا import شده توسط یک ماژول دیگه یا ماژول اصلی هست که باهاش برنامه رو اجرا کردن؟ اگر ماژول اصلی باشه که برنامه رو run کردن فانکشن main رو اجرا میکنه برنامه وارد main routine خودش میشه. شاید فکر کنید داخل زبانی مثل #Python و #JavaScript اینکار احمقانه باشه باتوجه به این که هر expressionـی رو میتونیم داخل top level خودمون اجرا کنیم. پس مزیت این کار چیه؟ جواب این هست که باتوجه به این که ما برنامه رو مینویسیم خب ما میدونیم کجا main routine رو اجرا کنیم ولی تصور کنید روی یک code base بزرگ رفتین و دنبال entrypoint میگردید. در این سناریو میتونه به عنوان داکیومنتیشن مناسب باشه. یا زمانی بخواید کدی رو اجرا کنید که فقط و فقط اگر کسی اون ماژول رو import کرده باشه و ... . همین الان هم وقتی پروژه #NestJS دارید bootstrap function دقیقا داره نقش main routine رو بازی میکنه و شما حتما باید اون رو اجرا کنید که برنامتون اجرا بشه. معمولا داخل #NestJS همچین چیزی میبینیم
function bootstrap() {
// init app
}
bootstrap();سناریویی رو در نظر بگیرد به هر دلیلی میخواید از این main.js یک چیزی رو import کنید( هرچند اگر همچین چیزی نیاز داشتید بهتره سعی کنید راه دیگه ای پیدا کنید ) و اگر شما این فایل رو import کنید داخل یک ماژول دیگه خب bootstrap اجرا میشه و ما این رو نمیخوایم. پس چیکار میتونیم کنیم؟
function bootstrap() {
console.log("hello");
}
if (import.meta.main) {
bootstrap();
} else {
console.log("imported");
}اینجا هست import.meta.main به کمک ما میاد حالا اگر شما مستقیما node main.js بزنید فانکشن bootstrap اجرا میشه ولی اگر از یک فایل دیگ مثل server.js داشته باشید و این فایل رو import کنید بخش else اجرا میشه و bootstrap هیچ وقت call نمیشه.
👍14
همیشه ما همه تلاش داریم کد با Performance خوب توسعه بدیم بدون این که این موضوع رو تصور کنیم که داخل کدبیس های #JavaScript معمولا Performance شوخیه.
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت ES2025 به #JavaScript اضافه شده صحبت کنیم که بهمون کمک میکنه که Performance بهتری داشته باشیم. سمت #NodeJS در بیزینس لاجیک های پیچیده میتونه معجزه کنه. برای #FrontEnd هم کاربردی هست ولی باتوجه به این که مرورگر های قدیمی ساپورت نمیکنن خب قطعا به این زودی استفاده ازش رو نمیبینیم.
ویژگی جدید ما اضاف شدن یک static method جدید به Iterator هست.
حالا سوال پیش میاد که چطور این به ما کمک میکنه. فرض کنید یک array بزرگ دارید و میخواید data رو map کنید به یک شکل دیگه و برای این کار یک pipeline از map ها رو ایجاد کردید:
در نگاه اول مشکلی نداره ولی اگر با عینک Performance ببینیم دوتا مشکل میبینیم.
1. برای هر map مجبوریم یکبار کامل loop بزنیم خب 3 بار loop میزنیم پس داریم O(3n)
2. هربار که یک loop کامل میزنیم هربار داریم یک Array جدید بعد از map ایجاد میکنیم. به صورت خلاصه هر .map برابر هست با یک Array allocation جدید. خب اینجا یک array اورجینال داریم و 3 تا map پس 4 تا array allocation داریم.
ممکنه برای تازه کارترها سوال های زیر پیش بیاد:
1. خب چرا اصلا این استایل کد میزنیم؟
2. چرا همه رو داخل یک map انجام نمیدیم؟
پاسخ سوال اول:
- میتونیم با for ... of کار رو بهتر با یک loop در بیاریم ولی مسئله این هست که معمولا برنامه نویس های #JavaScript در اینجور مواقع حتی بدون این که خودشون بدونن دیدگاه Functional Programming دارن و خب از اونجایی که به صورت فلسفی FP ذات Declarative داره و به صورت فلسفی کار کردن با API ها Declarative خیلی راحت تر و لذت بخش تر از Imperative هست همچین چیزی رو میبینیم.
- اگر هم خیلی کنجکاوید بیشتر بدونید وقتش هست نگاهی به #Elixir #Scala یا حتی Lambda ها در #Java اونجا قشنگ متوجه میشید. یا اصلا مسیر رو برعکس برید و نگاهی به رویکرد #Golang کنید و فرق زمین تا آسمونی رو ببینید.
پاسخ سوال دوم:
- در بزینس لاجیک های پیچیده برای خوانایی کد داشتن map های بیشتر خیلی بهتر از این هست که یک map بزرگ داشته باشیم. منطقی هم هست چون خیلی بهمون God Object ها رو یادآوری میکنه.
خب حالا سوال پیش میاد چیکار کنیم؟ خیلی ساده هست کافیه فقط خط اول رو به این شکل عوض کنیم و array رو تبدیل کنیم به Iterator.
خب دوباره الان سوال پیش میاد که WTF الان چی شد؟ سادس.
ما دیتا رو تبدیل کردیم به یک Iterator که ذات Iterator ها به صورت Lazy هست یعنی تا وقتی که نیاز به consume شدن data نباشه هیچ پردازشی انجام نمیشه و اگر هم نیاز به map کردن باشه دقیقا در runtime به صورت on-demand برای هر index تبدیل انجام میشه و ما نیازی به alloc کردن حافظه اضافه برای Array نداریم و هیچ loop اضافه ای هم درکار نیست.
حالا به این نکات توجه کنید:
- هر iterator رو فقط یکبار میشه consume کرد و اگر نیاز باشه باید دوباره ازش بسازی. در حقیقت با .toArray داریم consume کردن رو شبیه سازی میکنیم و دومی مقدار خالی به ما میده به خاطر iterator بودن.
- در این قسمت به map ها باید توجه کرد که با هر بار call شدن یک Array جدید نمیسازن بلکه یک Iterator جدید که روی Iterator قبلی سوار هست رو به ما میده! پس در نتیجه با توجه به تعریف Iterator که بالاتر گفتم نه loop اضافه ای داریم و نه alloc اضافه.
حالا اگر یکم بیشتر دقت کنی میبینیم خیلی شبیه به stream ها هست. اصلا این دوتا api به شدت باهم سازگار هستن. در این حد که استریم ها رو میشه تبدیل کرد به iterator و برعکس. بقیه کد هم دقیقا به صورت مشابهه کار میکنه.
دل نوشته:
حقیقتا دیگ نمیشه تفاوت بین stream, iterator, generator, rxjs, web stream, رو تشخیص داد😂. همشون رو میتونی جایگزین هم استفاده کنی. ( دلایل مختلفی برای وجود این همه api برای یک کار هست )
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت ES2025 به #JavaScript اضافه شده صحبت کنیم که بهمون کمک میکنه که Performance بهتری داشته باشیم. سمت #NodeJS در بیزینس لاجیک های پیچیده میتونه معجزه کنه. برای #FrontEnd هم کاربردی هست ولی باتوجه به این که مرورگر های قدیمی ساپورت نمیکنن خب قطعا به این زودی استفاده ازش رو نمیبینیم.
ویژگی جدید ما اضاف شدن یک static method جدید به Iterator هست.
Iterator.from()
حالا سوال پیش میاد که چطور این به ما کمک میکنه. فرض کنید یک array بزرگ دارید و میخواید data رو map کنید به یک شکل دیگه و برای این کار یک pipeline از map ها رو ایجاد کردید:
const data = [1, 2, 3, 4, 5];
const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);
در نگاه اول مشکلی نداره ولی اگر با عینک Performance ببینیم دوتا مشکل میبینیم.
1. برای هر map مجبوریم یکبار کامل loop بزنیم خب 3 بار loop میزنیم پس داریم O(3n)
2. هربار که یک loop کامل میزنیم هربار داریم یک Array جدید بعد از map ایجاد میکنیم. به صورت خلاصه هر .map برابر هست با یک Array allocation جدید. خب اینجا یک array اورجینال داریم و 3 تا map پس 4 تا array allocation داریم.
ممکنه برای تازه کارترها سوال های زیر پیش بیاد:
1. خب چرا اصلا این استایل کد میزنیم؟
2. چرا همه رو داخل یک map انجام نمیدیم؟
پاسخ سوال اول:
- میتونیم با for ... of کار رو بهتر با یک loop در بیاریم ولی مسئله این هست که معمولا برنامه نویس های #JavaScript در اینجور مواقع حتی بدون این که خودشون بدونن دیدگاه Functional Programming دارن و خب از اونجایی که به صورت فلسفی FP ذات Declarative داره و به صورت فلسفی کار کردن با API ها Declarative خیلی راحت تر و لذت بخش تر از Imperative هست همچین چیزی رو میبینیم.
- اگر هم خیلی کنجکاوید بیشتر بدونید وقتش هست نگاهی به #Elixir #Scala یا حتی Lambda ها در #Java اونجا قشنگ متوجه میشید. یا اصلا مسیر رو برعکس برید و نگاهی به رویکرد #Golang کنید و فرق زمین تا آسمونی رو ببینید.
پاسخ سوال دوم:
- در بزینس لاجیک های پیچیده برای خوانایی کد داشتن map های بیشتر خیلی بهتر از این هست که یک map بزرگ داشته باشیم. منطقی هم هست چون خیلی بهمون God Object ها رو یادآوری میکنه.
خب حالا سوال پیش میاد چیکار کنیم؟ خیلی ساده هست کافیه فقط خط اول رو به این شکل عوض کنیم و array رو تبدیل کنیم به Iterator.
const data = [1, 2, 3, 4, 5, 6]; ❌
const data = Iterator.from([1, 2, 3, 4, 5, 6]); ✅
خب دوباره الان سوال پیش میاد که WTF الان چی شد؟ سادس.
ما دیتا رو تبدیل کردیم به یک Iterator که ذات Iterator ها به صورت Lazy هست یعنی تا وقتی که نیاز به consume شدن data نباشه هیچ پردازشی انجام نمیشه و اگر هم نیاز به map کردن باشه دقیقا در runtime به صورت on-demand برای هر index تبدیل انجام میشه و ما نیازی به alloc کردن حافظه اضافه برای Array نداریم و هیچ loop اضافه ای هم درکار نیست.
حالا به این نکات توجه کنید:
- هر iterator رو فقط یکبار میشه consume کرد و اگر نیاز باشه باید دوباره ازش بسازی. در حقیقت با .toArray داریم consume کردن رو شبیه سازی میکنیم و دومی مقدار خالی به ما میده به خاطر iterator بودن.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
data.toArray()
data.toArray()
- در این قسمت به map ها باید توجه کرد که با هر بار call شدن یک Array جدید نمیسازن بلکه یک Iterator جدید که روی Iterator قبلی سوار هست رو به ما میده! پس در نتیجه با توجه به تعریف Iterator که بالاتر گفتم نه loop اضافه ای داریم و نه alloc اضافه.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);
حالا اگر یکم بیشتر دقت کنی میبینیم خیلی شبیه به stream ها هست. اصلا این دوتا api به شدت باهم سازگار هستن. در این حد که استریم ها رو میشه تبدیل کرد به iterator و برعکس. بقیه کد هم دقیقا به صورت مشابهه کار میکنه.
import { Readable } from "node:stream";
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
const streamData = Readable.from(data);دل نوشته:
حقیقتا دیگ نمیشه تفاوت بین stream, iterator, generator, rxjs, web stream, رو تشخیص داد😂. همشون رو میتونی جایگزین هم استفاده کنی. ( دلایل مختلفی برای وجود این همه api برای یک کار هست )
👍16
درود رفقا امیدوارم حالتون خوب باشه.
بلاخره تلسم رو شکوندم بعد از چند ماه این ویدیو رو گرفتم.
در این ویدیو باهم یاد میگیرم که چطور از AsyncLocalStorage استفاده کنیم در #NodeJS البته قبل از هرچیزی میریم نگاهی به react context در #React میکنیم که از بچه های #FrontEnd یاد بگیرم چطور همچین مسائلی رو که AsyncLocalStorage به ما کمک میکنه حل کنیم رو با react context حل میکنن.
https://youtu.be/B_s401HuZAU
بلاخره تلسم رو شکوندم بعد از چند ماه این ویدیو رو گرفتم.
در این ویدیو باهم یاد میگیرم که چطور از AsyncLocalStorage استفاده کنیم در #NodeJS البته قبل از هرچیزی میریم نگاهی به react context در #React میکنیم که از بچه های #FrontEnd یاد بگیرم چطور همچین مسائلی رو که AsyncLocalStorage به ما کمک میکنه حل کنیم رو با react context حل میکنن.
https://youtu.be/B_s401HuZAU
YouTube
برسی AsyncLocalStorage در #nodejs با کمک #react context
درود دوستان امیدوارم حالتون خوب باشه.
امروز در این ویدیو با هم دیگه یاد میگیریم که AsyncLocalStorage چی هست البته قبل از هرچیزی نگاهی به React و React context میکنیم چون برای درک بهتر AsyncLocalStorage خیلی به ما کمک میکنند.
کدهای مربوط به این ویدیو:
ht…
امروز در این ویدیو با هم دیگه یاد میگیریم که AsyncLocalStorage چی هست البته قبل از هرچیزی نگاهی به React و React context میکنیم چون برای درک بهتر AsyncLocalStorage خیلی به ما کمک میکنند.
کدهای مربوط به این ویدیو:
ht…
👍18
Node Master
در حال حاظر NodeJs برای هرکاری 3 API گاهی هم 2 API در دسترس شما قرار میده تا کارتون رو انجام بدید. به مثال زیر دقت کنید. import { readFile as readFileCps, readFileSync } from "node:fs"; import { readFile as readFilePromise } from "node:fs/promises"; // Sync…
یکی از معجزه های #JavaScript ویژگی Closure هست. البته هر زبانی که این ویژگی رو داشته باشه خیلی دست بازی برای پیاده سازی پترن هایی داره که بدون Closure ها شاید ممکن نباشه. خیلی وقت پیش درمورد Async Cps Style صحبت کردیم میتونید برید نگاهی بندازید. نکته ای که میخوایم امروز درموردش صحبت کنیم این که چه جادویی در این تکه کد ساده که به صورت روزانه مینویسیم و کار میکنیم وجود داره ولی خیلی ساده ازش رد میشیم چون کار میکنه! ولی داستان از فقط کار کردن پیچیده تره!
در این کد یک localScope داریم که مستقیما اشاره داره که این variable در localScope مربوط به asyncCPSTask تعریف شده و در حالت عادی وقتی به پایان فانکشن مربوطه میرسیم و از call stack خارج میشیم، localScope هم باید خارج بشه و رسما دیگه نداریمش. ( اگر هم refrence type باشه که GC زحمتش رو باید بکشه )
اگر نکته بالا رو در نظر داشته باشیم باید انتظار داشته باشیم که console.log به ما مقداری رو نشون نده چون به کمک setTimeout یک delay داریم برای اجرا کردن innerFn که قطعا در iteration های بعدی Event-loop اتفاق میافته و صدرصد مطمئن هستیم که تا اون موقع asyncCPSTask از call stack خارج شده. با وجود این موضوع که ما رسما از call stack خارج شدیم و runtime برای ما innerFN رو داخل iteration های بعدی Event-loop اجرا میکنه باز هم مقدار localScope رو میبینیم. دلیل این اتفاق و این رفتار Closure هست.
حالا برای درک بهتر این موضوع دوست دارم دقیقا متن کتاب JavaScript The Definitive Guide - David Flanagan (صفحه 204 بخش 8.6) بیارم:
جمله دوم دقیقا ساده ترین و قشنگ ترین تعریف برای این رفتار هست. به دلیل این که innerFn در زمان تعریف در local scope مربوط به asyncCPSTask قرار داشته میتونه از اون scope استفاده کنه و ما چون در innerFn یک refrence به متغییر localScope داریم رسما asyncCPSTask رو تبدیل کردیم به یک Closure برای innerFn و باتوجه به این که در این حالت مهم نیست فانکشن از کجا call میشه و فقط نکته مهم این هست که کجا تعریف شده فانکشن. حالا چه event-loop برای ما فانکشن رو کال کنه چه خودمون در هر صورت دسترسی به localScope داریم.
خیلی وقت پیش یک نگاهی به این ویژگی تقریبا داشتیم و باهاش decorator pattern رو به صورت کاربردی پیاده سازی کردیم و دیدیم.
https://news.1rj.ru/str/NodeMaster/115
function asyncCPSTask(cb) {
const localScope = "localScope";
function innrerFn() {
cb(localScope);
}
setTimeout(innrerFn, 1000);
}
asyncCPSTask((data) => console.log(data));در این کد یک localScope داریم که مستقیما اشاره داره که این variable در localScope مربوط به asyncCPSTask تعریف شده و در حالت عادی وقتی به پایان فانکشن مربوطه میرسیم و از call stack خارج میشیم، localScope هم باید خارج بشه و رسما دیگه نداریمش. ( اگر هم refrence type باشه که GC زحمتش رو باید بکشه )
اگر نکته بالا رو در نظر داشته باشیم باید انتظار داشته باشیم که console.log به ما مقداری رو نشون نده چون به کمک setTimeout یک delay داریم برای اجرا کردن innerFn که قطعا در iteration های بعدی Event-loop اتفاق میافته و صدرصد مطمئن هستیم که تا اون موقع asyncCPSTask از call stack خارج شده. با وجود این موضوع که ما رسما از call stack خارج شدیم و runtime برای ما innerFN رو داخل iteration های بعدی Event-loop اجرا میکنه باز هم مقدار localScope رو میبینیم. دلیل این اتفاق و این رفتار Closure هست.
حالا برای درک بهتر این موضوع دوست دارم دقیقا متن کتاب JavaScript The Definitive Guide - David Flanagan (صفحه 204 بخش 8.6) بیارم:
Like most modern programming languages, JavaScript uses lexical scoping. This
means that functions are executed using the variable scope that was in effect when
they were defined, not the variable scope that is in effect when they are invoked
جمله دوم دقیقا ساده ترین و قشنگ ترین تعریف برای این رفتار هست. به دلیل این که innerFn در زمان تعریف در local scope مربوط به asyncCPSTask قرار داشته میتونه از اون scope استفاده کنه و ما چون در innerFn یک refrence به متغییر localScope داریم رسما asyncCPSTask رو تبدیل کردیم به یک Closure برای innerFn و باتوجه به این که در این حالت مهم نیست فانکشن از کجا call میشه و فقط نکته مهم این هست که کجا تعریف شده فانکشن. حالا چه event-loop برای ما فانکشن رو کال کنه چه خودمون در هر صورت دسترسی به localScope داریم.
خیلی وقت پیش یک نگاهی به این ویژگی تقریبا داشتیم و باهاش decorator pattern رو به صورت کاربردی پیاده سازی کردیم و دیدیم.
https://news.1rj.ru/str/NodeMaster/115
👍10
این اولین بلاگ پست یکی از نزدیک ترین دوستان من هست که داخل AMD منتشر شده و درمورد استفاده از #k8s برای نیاز های AI برای کارت گرافیک ها AMD هست.
دوست داشتید نگاهی بندازید مخصوصا اگر #K8S آشنایی دارید.
https://rocm.blogs.amd.com/software-tools-optimization/gpu-operator-partitioning/README.html
دوست داشتید نگاهی بندازید مخصوصا اگر #K8S آشنایی دارید.
https://rocm.blogs.amd.com/software-tools-optimization/gpu-operator-partitioning/README.html
ROCm Blogs
GPU Partitioning Made Easy: Pack More AI Workloads Using AMD GPU Operator
What’s New in AMD GPU Operator: Learn About GPU Partitioning and New Kubernetes Features
👍11
ما Developer ها به Magic عادت داریم. بیشتر وقت ها کدی که مینویسیم فقط میخوایم کار کنه. اما چطور کار کردن اون کد خیلی اهمیتی نداره تا وقتی که کدمون کار میکنه. حالا چه به صورت جادویی کار کنه چه با جزئیات کامل بدونیم پشت پرده چخبر هست. گاها بعضی از این جادو ها اینقدر پیچیده و ترسناک به نظر میان که اصلا بهشون نزدیک نمیشیم. یکی از این Magic ها Promise ها در #JavaScript هست. اکثرا فکر میکنیم یک چیزی هست که داخل گوشت و وجود #JavaScript فرو رفته و به هیچ عنوان نمیشه تغییرش داد یا اگر هم بشه خیلی سخت هست. کاری به پیاده سازی اصلیش امروز نداریم. امروز بعد از این مقدمه طولانی میخواهیم باهم یاد بگیرم چطور یک Object بسازیم که شبیه به Promise عمل میکنه. یعنی میتونیم await کنیم اون رو با وجود این که اصلا اون Promise نیست و یک Object ساده هست. به این کد پایین دقت کنید.
معمولا اولین واکنش افراد به این تکه کد "WTF" هست. داستان از این قرار هست که خیلی قبل تر از این که Promise ها به صورت استاندارد وارد #JavaScript بشن پیاده سازی های مختلف ازش وجود داشته و هرکدوم implemention detail خاص خودشون رو داشتن ولی طی گذر زمان بلاخره رسیدن به این interface که الان داریم هر روز باهاش کار میکنیم ( تقریبا شبیه به وضعیت decorator ها و پروپزوال مربوط بهش ). بزارید یکم بیشتر وارد داستان بشیم.
برای این که بتونیم یک object رو await کنیم لزوما نیازی نداره حتما یک instance از Promise باشد. بلکه هر object که Promise-like باشد میتواند await بشود. این تعریف دقیقا تعریف Duck-typing هست که قبلا مفصل درموردش حرف زدیم. حالا سوال پیش میاد که Promise-like یعنی چی؟
- هر class که thanable interface را implement کند میتوان آن را await کرد.
پس میتونیم نتیجه بگیریم که همه Promise ها thenable هستند ولی همه thenable ها Promise نیستند.
حالا میرسیم که thanable interface چیست؟ در ساده ترین حالت دقیقا مثال بالا رو در نظر بگیرد. یک object یا class که then method رو که با دوتا argument که هردو callback هستن یکی برای وقتی که reject شده و یکی برای وقتی resolve میشه invoke میشود و ما میتونیم با اون دوتا رفتاری که Promise-like هست رو از خودمون نشون بدیم.
حالا این ویژگی به ما اجازه داده که پکیج های معروفی مثل promise-retry ببینیم یا حتی یکم تلاش کنیم به کمک Promise-like ها در ES5 بتونیم چیزی شبیه بهش رو داشته باشیم که البته این موضوع خودش یک بحث دیگس اگر دوست دارید نگاهی به promise-polyfill یا babel-polyfill بندازید.
این هم پست مربوط به duck typing به نظرم نگاهی بندازید:
https://news.1rj.ru/str/NodeMaster/128
const thenable = {
then(resolve, reject) {
setTimeout(() => resolve("Hello from thenable!"), 1000)
},
}
const txt = await thenable
console.log(txt)معمولا اولین واکنش افراد به این تکه کد "WTF" هست. داستان از این قرار هست که خیلی قبل تر از این که Promise ها به صورت استاندارد وارد #JavaScript بشن پیاده سازی های مختلف ازش وجود داشته و هرکدوم implemention detail خاص خودشون رو داشتن ولی طی گذر زمان بلاخره رسیدن به این interface که الان داریم هر روز باهاش کار میکنیم ( تقریبا شبیه به وضعیت decorator ها و پروپزوال مربوط بهش ). بزارید یکم بیشتر وارد داستان بشیم.
برای این که بتونیم یک object رو await کنیم لزوما نیازی نداره حتما یک instance از Promise باشد. بلکه هر object که Promise-like باشد میتواند await بشود. این تعریف دقیقا تعریف Duck-typing هست که قبلا مفصل درموردش حرف زدیم. حالا سوال پیش میاد که Promise-like یعنی چی؟
- هر class که thanable interface را implement کند میتوان آن را await کرد.
پس میتونیم نتیجه بگیریم که همه Promise ها thenable هستند ولی همه thenable ها Promise نیستند.
حالا میرسیم که thanable interface چیست؟ در ساده ترین حالت دقیقا مثال بالا رو در نظر بگیرد. یک object یا class که then method رو که با دوتا argument که هردو callback هستن یکی برای وقتی که reject شده و یکی برای وقتی resolve میشه invoke میشود و ما میتونیم با اون دوتا رفتاری که Promise-like هست رو از خودمون نشون بدیم.
حالا این ویژگی به ما اجازه داده که پکیج های معروفی مثل promise-retry ببینیم یا حتی یکم تلاش کنیم به کمک Promise-like ها در ES5 بتونیم چیزی شبیه بهش رو داشته باشیم که البته این موضوع خودش یک بحث دیگس اگر دوست دارید نگاهی به promise-polyfill یا babel-polyfill بندازید.
این هم پست مربوط به duck typing به نظرم نگاهی بندازید:
https://news.1rj.ru/str/NodeMaster/128
Telegram
Node Master
امروز درمورد Duck Typing صحبت میکنیم. این موضوع مربوط به رفتار زبان های dynamic type میباشد. البته این تکنیک در زبان هایی static type هم در حالت های خاصی استفاده میشود. برای درک این موضوع با مثال در #Python شروع میکنیم.
class Duck:
def fly(self):
…
class Duck:
def fly(self):
…
👍11
درود دوستان امیدوارم حالتون خوب باشه. ورژن #NodeJS جدید 24.11 به صورت LTS منتشر شد.
https://nodejs.org/en/blog/release/v24.11.0
https://nodejs.org/en/blog/release/v24.11.0
nodejs.org
Node.js — Node.js v24.11.0 (LTS)
Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and noscripts.
👍19
درود دوستان امیدوارم حالتون خوب باشه.
به عنوان Backend developer از موضوعاتی که حتما باید حداقل آشنایی کوچکی داشته باشید کار کردن با container ها هست. به طوری که حداقل بتونید پروژه خودتون رو به راحتی containerized کنید. در این مورد زیاد course دیدم معمولا خیلی از کورس ها اضافه گویی میکنند و تایم زیادی هم لازم دارن.
این کورس از Brian Holt از محدود course هایی هست که این اضافه گویی ها رو نداره و البته موضوع خیلی جالب و مهمی هم که اشاره میکنه این هست که کلا قبل از این که وارد بحث docker بشه با cgroup و namespace سعی میکنه یک نسخه ساده از docker رو ایجاد کنه و همین موضوع خیلی بهتون دید بهتری نسبت به این تکنولوژی میده.
- این course برای افراد مبتدی مناسب هست.
- این course برای افرادی که docker بلد هستن و میخوان شروع کنن داکیومنت docker رو بخونن و عمیق تر بشن ولی قبلش نیاز به یک review دارن بسیار پیشنهاد میشه.
- برای دوستانی که Advance هستن ممکنه چیز خاصی یاد بهشون اضاف نکنه و تکرار چیزایی باشه که بلد هستن. پس اگر از این دسته افراد هستین حتما دقت کنید.
https://downloadly.ir/elearning/video-tutorials/complete-intro-to-containers-v2/
به عنوان Backend developer از موضوعاتی که حتما باید حداقل آشنایی کوچکی داشته باشید کار کردن با container ها هست. به طوری که حداقل بتونید پروژه خودتون رو به راحتی containerized کنید. در این مورد زیاد course دیدم معمولا خیلی از کورس ها اضافه گویی میکنند و تایم زیادی هم لازم دارن.
این کورس از Brian Holt از محدود course هایی هست که این اضافه گویی ها رو نداره و البته موضوع خیلی جالب و مهمی هم که اشاره میکنه این هست که کلا قبل از این که وارد بحث docker بشه با cgroup و namespace سعی میکنه یک نسخه ساده از docker رو ایجاد کنه و همین موضوع خیلی بهتون دید بهتری نسبت به این تکنولوژی میده.
- این course برای افراد مبتدی مناسب هست.
- این course برای افرادی که docker بلد هستن و میخوان شروع کنن داکیومنت docker رو بخونن و عمیق تر بشن ولی قبلش نیاز به یک review دارن بسیار پیشنهاد میشه.
- برای دوستانی که Advance هستن ممکنه چیز خاصی یاد بهشون اضاف نکنه و تکرار چیزایی باشه که بلد هستن. پس اگر از این دسته افراد هستین حتما دقت کنید.
https://downloadly.ir/elearning/video-tutorials/complete-intro-to-containers-v2/
دانلود رایگان نرم افزار
دانلود Frontend Masters - Complete Intro to Containers, v2 2024-8
دانلود Frontend Masters - Complete Intro to Containers, v2 2024-8 . دوره آموزشی ساخت کانتینر با Docker منتشر شده توسط FrontendMasters
👍17