Node Master
1.02K subscribers
24 photos
2 files
156 links
Group Chat: @nodemastergp
Admin: @napoleon_n1
Download Telegram
چند روزی هست که #Deno نسخه 1.46 منتشر شده.
از نکات جالبی که اضافه شده
deno serve --parallel

این flag یکجورایی شبیه به cluster در #NodeJS عمل میکنه. البته اگر درموردش مطالعه کنید تفاوت هایی هست.
- آپدیت بعدی مربوط به deno fmt هست که فرمت های مختلف مثل html css ,scss, yml و ... رو هم انجام میده.
- یکی از تغیرات مهم دیگ پایدار شدن std مربوط به #Deno هست. نکته جالب در این مورد این هست که این std ها رو شما میتونید روی پروژه های #NodeJS خودتون هم استفاده کنید.

و از همه مهتر Deno 2 خیلی نزدیک هست و این آپدیت یعنی نسخه 1.46 آخرین آپدیت نسخه 1.X میباشد.
https://deno.com/blog/v1.46
👍3
چندین بار سعی کردم با معماری #Microservice دقیق تر آشنا بشم ولی همیشه به دلیل پیچیده بودن pattern ها لینک کردن بین مطالب زیاد موفق نبود و البته یکی از منابع خوبی که برای عمیق شدن وجود داره کتاب Building Microservices Book by Sam Newman هست.
امروز این دوره 2 ساعته رو نگاه کردم. به صورت خیلی Big picture درمورد #Microservice صحبت میکنه و البته بعضی مفاهیم هم با code snippet های خیلی ساده #NodeJS و #Express توضیح میده. پیشنهاد میکنم اگر قصد دارید #Microservice عمیق تر بشید و اگر مثل من زیاد در این مورد نمیدونید اول این دوره رو نگاه کنید و بعد مفاهیم و نکات این دوره رو هرکدوم به عنوان یک سرفصل یا سرتیتر برای مطالعه بیشتر و عمیق تر شدن استفاده کنید. به نظرم مقدمه خوبی هست قبل از مطالعه کتابی که بالاتر گفتم.

https://downloadly.ir/elearning/video-tutorials/node-js-microservices-the-big-picture/

#course
👍16
یکی از نکات زیبا که درمورد #Deno و #JSR که وجود داره این هست که شما میتونید از پکیج های std دینو در #NodeJS استفاده کنید. همشون نه ولی به اکثرشون دسترسی دارید. به لینک زیر یک نگاهی بندازید و مشخصا میبینید که کدوم پکیج ها رو میتونید در پروژه #NodeJS خودتون استفاده کنید.
https://jsr.io/@std
به عنوان مثال پکیج @std/msgpack به پروژه خودمون اضافه میکنیم.
npx jsr add @std/msgpack

و بعد کد زیر رو با #NodeJS اجرا کنید.
import * as msgpack from "@std/msgpack";

const data = { name: "node-master" };

const enc = msgpack.encode(data);
const dec = msgpack.decode(enc);
console.log(dec);

حالا سوال پیش میاد که اصلا چرا همچین کاری باید کنیم. باتوجه به این که #JavaScript خودش std بزرگی مثل #Python یا #Java نداره گاهی اوقات نیاز به یک سری کدهای کمکی برای پروژه خودتون دارید و پکیج هایی مثل Lodash, es-toolkit کمک بزرگی کردن. اما حالا #Deno هم با این کار به اکوسیستم کمک بزرگی کرده و یک رنج از ابزار های کمکی که ممکنه در loadash و بقیه شبیهه بهش پیدا نکنید رو شاید اینجا پیدا کنید.

به عنوان مثال اگر پروژه کوچیکی دارید که فقط یک instance از server شما وجود داره استفاده از ابزاری مثل #Redis صرفا برای Cache زیاد منطقی نیست و خب در اکثرا اوقات یک Map ساده مشکل شما رو میتونه حل کنه. اگر ویژگی TTL هم بخواید داشته باشید خودتون میتونید پیاده سازی کنید با کمک Map ولی معمولا از پکیج node-cache در این سناریو استفاده میکنن. حالا یک گزینه دیگ داریم که مربوط به #Deno std هست.
https://jsr.io/@std/cache
این پکیج جدا از مثال بالا مدل های مختلف دیگ از cache رو در اختیار شما میزاره که نگاهی بندازید و جالبه.
👍5
وقتی در حال توسعه با #NodeJS هستید یکی از مشکلاتی که در حال حاظر وجود داره استفاده از #TypeScript در هنگام توسعه میباشد. باتوجه به آپدیت های اخیر #NodeJS حرکت هایی جهت پشتیبانی راحت #TypeScript در #NodeJS با اضافه کردن فلگ های --experimental-transform-types و --experimental-strip-types تغییراتی داشته ولی همچنان تا Production ready بودن خیلی فاصله داره. گزینه های که میتونه بهتون در این مورد کمک کنه استفاده از ts-node و tsx هست.
در یک سال گذشته شخصا از هردو در پروژه های مختلف استفاده کردم. با توجه به آزمون و خطایی که من کردم در حال حاظر tsx خیلی خیلی بهتر از ts-node هست و کارتون رو به خوبی راه میندازه.
https://tsx.is/
👍10
یکی از کسایی که در کامینیوتی #NodeJS میتونید خیلی چیزا ازش یاد بگیرید Matteo Collina سازنده فریم ورک #Fastify و کلی ابزار Open source دیگ برای #NodeJs .
تا حالا چندین ویدیو از ایشون دیدم و خیلی نکات ریزی رو یاد گرفتم که اگر خودم بخوام به اون ها برسم رسما سال ها زمان میبره.
پیشنهاد میکنم این ویدیو رو حتما ببینید.
- نکته جالبی که در این ویدیو برای من بود عمق فریم ورک #Fastify بود که به برای ریز ترین مشکلات هم یک راه حلی وجود داره.
- من شخصا با #Jest به شدت مشکل دارم و در این ویدیو یک دلیل بسیار بسیار ترسناک و بزرگ رو اشاره میکنه که این مشکل رو به تنفر نسبت به #Jest تبدیل کرد.

https://www.youtube.com/watch?v=HyOuKN6KYqo
👍11
مدت زیادی هست که #Redis Stack منتشر شده ولی هنوز خیلی ها به Redis به چشم یک دیتابیس Key-Value ساده نگاه میکنند و از 90 درصد قابلیت هاش استفاده نمیکنند. پیشنهاد میکنم داکیومنت مربوط بهش رو حتما بخونیدتا تمام ویژگی هایی رو که داره ببینید.
دوتا از ویژگی های خوبی که Redis Stack داره به اسم Redis Search و Redis JSON هست.

- تا قبل از Redis JSON برای ذخیره کردن JSON ها در Redis، معادل Serialize شده رو به صورت Key-Value ذخیره میکردن و یا گاهی به صورت Map باهاش رفتار میکردن. حالا شما با Redis JSON میتونید مثل یک document oriented database مثل MongoDB رفتار کنید. ( البته Query ها به صورت پیش فرض محدودیت هایی دارند )
- تا قبل از Redis Search برای سرچ کردن تنها گزینه موجود استفاده از Glob Pattern ها بود که حتی داخل خود داکیومنت هم پیشنهاد کرده بودن که اگر روی Production هستید سعی کنید زیاد استفاده از Glob pattern نکنید. و این موضوع با در نظر گرفتن این نکته که Redis به صورت ذاتی Single thread هست و Event loop رو با این کار در حجم زیاد دیتا بلاک میکنید منطقی هست. البته این موضوع برای دوستان #JavaScript و #NodeJS کاملا به صورت واضح قابل درک هست. حالا شما با استفاده از Redis Search میتونید روی دیتا مورد نظرتون Index بزارید و باتوجه به اون Index و Schema که تعریف کردین Query بزنید و دیتا رو خیلی سریع و تمیز دریافت کنید. انتظار قدرت SQL و بقیه دیتابیس ها مثل MongoDB رو نداشته باشید ولی در بعضی سناریو ها واقعا ترکیب Redis Json و Redis Search میدرخشه.
در این مثال با نحوه کار کردن با Redis JSON آشنا میشیم و در پست بعدی با Redis Search یک خورده کار میکنیم.
به صورت کلی شما با استفاده از "JSON" میتونید دسترسی به namespace مربوط بهش رو داشته باشید و با json ها کار کنید.

- ایجاد یک Json doc جدید
JSON.SET key path value

با استفاده از JSON.SET میتونید JSON به راحتی ذخیره کنید. در اینجا key منظور از همون کلید عادی هست نکته خاصی نداره ( در Redis Search درموردش بیشتر صحبت میکنیم ). منظور از Path اینجا مسیر JsonPath هست که با استفاده از اون میتونید فیلتر های مختلف روی دیتا Json بزارید و بخش خاصی رو فقط بخونید یا آپدیت کنید ( معادل Xpath برای داده های XML ). برای این که بتونیم یک دیتا json ذخیره کنیم خب ما میخوایم در مسیر Root این کلید ذخیره کنیم و با استفاده از "$" مشخص میکنیم که میخوایم روی Root ذخیره کنیم.
JSON.SET user:1 $ '{"name": "Iman", "age": 25, "city": "Bushehr"}'

حالا اگر بخوام فقط بخش name رو بخونم از این به این صورت عمل میکنم.
JSON.GET user:1 "name"

یا اگر بخوام شهر رو آپدیت کنم به تهران.
JSON.SET user:1 $.city '"Tehran"'

حالا اگر بخوایم کل دیتا بخونیم و نتیجه رو ببینیم.
JSON.GET user:1

یک نکته خیلی مهم و ریز درمورد آپدیت بگم. جایی که دیتا رو قرار میدیم یعنی '"Tehran"' هر مدل دیتایی میخواد باشه مثل اینجا که یک string ساده هست. باید یک parser مربوط به JSON بتونه به صورت Valid این دیتا رو Serialize کنه. به عنوان مثال یعنی عبارت زیر در #JavaScript باید بدون هیچ خطایی کار کنه.
> JSON.stringify("Tehran")
'"Tehran"'

در صورتی که JSON.stringify به شما خروجی داد شما اون دیتا رو میتونید به عنوان value استفاده کنید.
حالا برا این که مثال رو یکم جالب تر کنیم یک Json دیگ رو داخل این Embed میکنیم.
JSON.SET user:1 $.address '{"zipCode":1234}'
JSON.GET user:1 $.address.zipCode

در پست بعدی به Redis Search نگاه میندازیم و اگر انرژی هم موند یکی از مهم ترین و اساسی ترین نکات Redis که دونستنش میتونه مثل مرگ و زندگی باشه یعنی Atomicity رو برسی میکنیم.
امیدوارم موفق باشید.
👍19
چند روزی هست #NodeJS نسخه 23 منتشر شده و بزودی 22 LTS رو میبینیم.
سعی میکنم تغییرات رو باهم برسی کنیم در آینده.
https://nodejs.org/en/blog/release/v23.0.0
👍13
یک پکیج خیلی کوچیک و کاربردی که میتونید در پروژه های خودتون و حتی Github action استفاده کنید تا اگر مشکل امنیتی در ورژن مورد استفاده شما در #NodeJS وجود داره با خبر بشید و در صورت نیاز آپدیت کنید
فقط کافی هست که با npx این پکیج رو ران کنید.
npx is-my-node-vulnerable

https://www.npmjs.com/package/is-my-node-vulnerable
👍12
یک بخش جدید به داکیومنت #NodeJS از ورژن 22 اضافه شده برای TypeScript.
خودش پیشنهاد میکنه از tsx استفاده کنیم برای NodeJS.

به صورت کلی فاصله زیادی داریم تا #NodeJS هم مثل #Bun و #Deno به صورت کامل و Stable از #TypeScript ساپورت کنه. داخل این داکیومنت در این مورد توضیحات مربوطه داده شده.
درکل برای پروژه Production درکل tsx یا ts-node گزینه منطقی تری هست.
https://nodejs.org/docs/latest-v22.x/api/typescript.html
#Update
👍11
درود خدمت شما دوستان.
const lst = []
lst.map()

موضوعی که امروز در این ویدیو میخواهیم عمیق درموردش صحبت کنیم این هست که چرا همین یک خط کد کوچک در بالا باعث میشه سرور #NodeJS نابود بشه و کلا نتونه هیچ Response رو به کاربر بده.
در این مسیر نگاهی میکنیم به یکی خفن ترین ویژگی های #NodeJS یعنی Readable استریم ها و یاد میگیریم که چطور با استفاده از اون ها یعنی
Readable.from()

یک برنامه بسیار Optimize تری داشته باشیم.
https://youtu.be/N0akLbvhShE?si=f623-vxXz-brA4ag
👍13
درود دوستان ارادت.
امیدوارم حالتون خوب باشه.
// lib code
func doSomething() <-chan int {
ch := make(chan int)

go func() {
defer close(ch)
time.Sleep(2 * time.Second)
ch <- 102

}()

return ch
}

// main code
func main() {
result := <-doSomething()
fmt.Println(result)
}

همیشه مفهوم Concurrency برای ما Developer ها مثل یک Super Power هست و البته به دست آوردن این Super Power هم کار راحتی نیست.
قبلا کتاب Learning Go رو من مطالعه میکردم و یک پاراگراف از این کتاب برای من خیلی جذاب بود چون نگرش من درمورد این موضوع و این Super Power تا حد خیلی زیادی تغییر داد.
در این ویدیو سعی میکنیم یک طرز تفکر و یک رویکرد رو برسی کنیم که بتونیم در آینده زیر ساخت مناسبی برای شنا کردن در دریای عمیق Concurrency ها در آینده داشته باشیم.
نکته اصلی این ویدیو مفهوم و طرز تفکری هست که از اون پاراگراف در کتاب یاد گرفتم و امیدوارم تونسته باشم به خوبی اون رو منتقل کنم.

https://youtu.be/fbh_r9CKmMU
👍14
درود دوستان ارادتتتت.
خیلی وقت بود میخواستم این ویدیو رو بگیرم. روزی که من #Python گذاشتم کنار و حرفه ای شروع به کد زدن #JavaScript و #NodeJS کردم همیشه هروقت باکسی بحث برنامه نویسی میشد من این رو میگفتم که جای یک چیزی مثل Context Manager مثل پایتون در اکوسیستم #JavaScript واقعا خالی هست. وقتی #TypeScript ورژن 5.2 منتشر شد و این syntax رو برای بار اول دیدم واقعا خوشحال شدم
async function main() {
using resource1 = getResource()
await using resource2 = await getResource()
}

در این ویدیو به Explicit Resource Management در زبان های برنامه نویسی #python , #golang و #cpp میکنیم. با یک پترن خیلی قدیمی به اسم RAII پترن آشنا میشیم و در نهایت میرسیم به ارتباط RAII پترن در C++ در #Typescript .
این ویدیو قرار هست در دو پارت منتشر بشه و پارت دوم رو کامل درمورد مثال های عملی #Typescript گذاشتیم و تمرکز ویدیو اول هم بیشتر نگاه به زبان های دیگر و برسی این موضوع که چرا به "using" نیاز داریم.

https://youtu.be/0CG_WA6Yu9o?si=QYunevpiEyWp6gWW
👍13
چند روزی هست #NodeJS نسخه 22.12 LTS منتشر شده و شاهد یکی از بزرگترین قدم های #NodeJS برای آینده هستیم.
در این ورژن میشه ماژول های ESM رو در CJS بدون استفاده از --experimental-require-module فلگ استفاده کرد. این موضوع باعث میشه که اکوسیستم بیشتر سمت ESM بره و استفاده از CJS کمتر بشه.

https://nodejs.org/en/blog/release/v22.12.0

#Update
👍11
درود و خسته نباشید دوستان امیدوارم حالتون خوب باشه.
اگر با lib هایی مثل #jest و #vitest برای پروژه هاتون تست نوشته باشید و البته بعد تلاش کرده باشین که سوییچ کنید روی std test runner خود #NodeJS که خیلی هم از Stable شدنش نمیگذره.
یکی از بزرگترین مشکلاتی که این Test runner داشت و تست نوشتن رو در یک سناریو واقعا آزار دهنده میکرد در آپدیت 22.17 LTS فیکس شده.
assert.partialDeepStrictEqual()

گاهی اوقات پیش میاد که میخواید یک subset از یک object رو assert کنید و نمیخواید کل اون attr های اون object رو assert کنید. تا قبل از این آپدیت این سناریو در STD test runner غیرممکن بود. شخصا واقعا خوشحالم که این رو خیلی سریع متوجه شدن و اضاف کردن چون همه چیزش خیلی خوب شده و فقط همین یدونه کم بود.
👍11
سلام و درود دوستان امیدوارم حالتون خوب باشه.
یک نکته ای که همیشه در پروژه ها میبینم چه در پروژه های 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 دیدیم که اضافه شد. برا این که وارد بحث بشیم دوست دارم با این کد پایتون شروع کنم.
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.iss.oneta.main) {
bootstrap();
} else {
console.log("imported");
}

اینجا هست import.iss.oneta.main به کمک ما میاد حالا اگر شما مستقیما node main.js بزنید فانکشن bootstrap اجرا میشه ولی اگر از یک فایل دیگ مثل server.js داشته باشید و این فایل رو import کنید بخش else اجرا میشه و bootstrap هیچ وقت call نمیشه.
👍14
همیشه ما همه تلاش داریم کد با Performance خوب توسعه بدیم بدون این که این موضوع رو تصور کنیم که داخل کدبیس های #JavaScript معمولا Performance شوخیه.
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت 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
👍18