دسته‌بندی نشده

درک ژنراتورها در JavaScript

مقدمه
در ECMAScript 2015 ، ژنراتورها (آزانگرها) به زبان JavaScript معرفی شدند. ژنراتورفرایندی است که می تواند متوقف شده و از سر گرفته شود و می تواند مقادیر مختلفی را ارائه دهد. ژنراتور در جاوا اسکریپت از یک تابع ژنراتور تشکیل شده است ، که یک مفعول Generator تکرارگر را برمی گرداند.
ژنراتورها می توانند حالت خود را حفظ کنند ، روشی کارآمد برای ایجاد تکرارگرها ارائه دهند ، و قادر به کار با داده های نامتناهی هستند که می توانند برای اجرای اسکرول نامحدود در یک برنامه وب ، کار با داده های موج صدا و موارد دیگر استفاده شوند. علاوه بر این ، در هنگام استفاده به همراه promise ها ، می توانند از تابع async/await استفاده کنند ، که به ما امکان می دهد با کد غیرهمزمان با روشی ساده تر و خواناتر سر و کار داشته باشیم. اگرچه async / await روشی معمول تر برای کار با موارد استفاده معمول، ساده و غیر همزمان، مانند گرفتن داده ها از یک API است، ژنراتورها ویژگی های پیشرفته تری دارند که یادگیری نحوه استفاده از آنها را ارزشمند می کند.
در این مقاله ، ما نحوه ایجاد توابع ژنراتور ، نحوه تکرار آبجکت های ژنراتور ، تفاوت بین yield  و return  در داخل ژنراتور و سایر جنبه های کار با ژنراتور را پوشش خواهیم داد.
توابع ژنراتور
یک تابع ژنراتور تابعی است که یک آبجکت Generator را برمی گرداند و همانطور که در شکل زیر نشان داده شده است توسط کلید واژه function  به همراه ستاره (*) تعریف می شود:
// Generator function declaration
function* generatorFunction() {}

گاهی اوقات ، ستاره را در کنار نام تابع و مقابل کلمه کلیدی تابع مانند function *generatorFunction() ، مشاهده می کنید. این هم به همان صورت عمل میکند ، اما function* به طور گسترده تری پذیرفته شده است.
توابع ژنراتور نیز مانند توابع معمولی می تواند در یک عبارت تعریف شود:
// Generator function expression
const generatorFunction = function*() {}

ژنراتورها حتی می توانند روشهای یک آبجکت یا کلاس باشند:
// Generator as the method of an object
const generatorObj = {
*generatorMethod() {},
}

// Generator as the method of a class
class GeneratorClass {
*generatorMethod() {}
}

مثالهای موجود در طول این مقاله از دستور اعلان تابع ژنراتور استفاده می کنند.
توجه: بر خلاف توابع معمولی ، ژنراتورها را نمی توان با کلمه کلیدی new ساخت ، و همچنین نمی توان آنها را همراه با توابع آرایه ای استفاده کرد.

اکنون که می دانید چگونه می توانید توابع ی ژنراتور را اظهار کنید ، بیایید به آبجکت های ژنراتور تکرارگر که باز می گردند نگاهی بیندازید.
آبجکت های ژنراتور
به طور معمول ، توابع موجود در جاوا اسکریپت تا زمان اتمام اجرا میشوند ، و فراخوانی یک تابع با رسیدن به کلمه کلیدی return ، مقداری را برمی گرداند. در صورت حذف کلمه کلیدی return ، یک تابع به طور ضمنی undefined را باز خواهد گرداند.
به عنوان مثال در کد زیر یک تابع sum () را اعلام می کنیم که مقداری را برمی گرداند که جمع آن دو عدد صحیح است:
// A regular function that sums two values
function sum(a, b) {
return a + b
}

فراخوانی تابع مقداری را نشان می دهد که مجموع آرگومان ها است:
const value = sum(5, 6) // 11
Copy

با این حال ، تابع ژنراتور ، یک مقدار را فوراً بر نمی گرداند ، و در عوض یک آبجکت ژنراتور تکرارگر را برمی گرداند. در مثال زیر ، یک تابع را اعلام می کنیم و مانند یک تابع استاندارد ، تک مقدار برگشتی به آن می دهیم:
// Declare a generator function with a single return value
function* generatorFunction() {
return ‘Hello, Generator!’
}

هنگامی که ما از تابع ژنراتور درخواست می کنیم ، آبجکت ژنراتور را برمی گرداند ، که می توانیم به یک متغیر اختصاص دهیم:
// Assign the Generator object to generator
const generator = generatorFunction()

اگر یک تابع معمولی بود ، انتظار داشتیم که ژنراتور رشته ای را که در این تابع برگشته است به ما بدهد. با این حال ، آنچه در واقع دریافت می کنیم یک آبجکت در حالت suspended  است. بنابراین فراخوانی generator  خروجی مشابه موارد زیر را نشان می دهد:
Output
generatorFunction {<suspended>}
__proto__: Generator
[[GeneratorLocation]]: VM272:1
[[GeneratorStatus]]: “suspended”
[[GeneratorFunction]]: ƒ* generatorFunction()
[[GeneratorReceiver]]: Window
[[Scopes]]: Scopes[3]

آبجکت Generator  که توسط تابع برگشت داده شده ، یک تکرارگر است. تکرارگر آبجکتی است که یک روش next() در دسترس دارد که برای تکرار از طریق دنباله ای از مقادیر استفاده می شود. روش next() یک آبجکت با ویژگی های value  و done  برمی گرداند. value  نشان دهنده مقدار برگشتی است ، و done  نشان می دهد که آیا تکرارگر تمام مقادیر خود را اجرا کرده است یا نه.
با دانستن این موضوع ، بیایید next() را روی ژنراتور خود فراخوانی کنیم و مقدار و وضعیت فعلی تکرارگر را بدست آوریم:
// Call the next method on the Generator object
generator.next()

خروجی زیر را ارائه می دهد:
Output
{value: “Hello, Generator!”, done: true}

مقدار برگشتی از فراخوانی next()،Hello, Generator! است و وضعیت done ، true میباشد ، زیرا این مقدار از return حاصل می شود که تکرارگر را بسته است. از آنجا که تکرار انجام شده است ، وضعیت تابع ژنراتور از حالت suspended  به closed تغییر می کند. دوباره فراخوانی generator  خروجی زیر را ارائه می دهد:
Output
generatorFunction {<closed>}

در حال حاضر ، ما فقط نشان داده ایم که چگونه یک تابع ژنراتور می تواند روشی پیچیده تر برای بدست آوردن مقدار return  یک تابع باشد. اما توابع ژنراتور همچنین دارای ویژگی های منحصر به فردی هستند که آنها را از توابع طبیعی متمایز می کند. در بخش بعدی ، ما در مورد اپراتور yield  خواهیم آموخت و میبینیم که چگونه یک ژنراتور می تواند مکث کرده و اجرا را از سر بگیرد.
عملگرهای yield
ژنراتورها یک کلمه کلیدی جدید به نام yield را به JavaScript معرفی می کنند. yield  می تواند یک تابع ژنراتور را متوقف کرده و مقداری را که بعد از yield  میاید ، بازگرداند و راهی ساده برای تکرار مقادیر فراهم می کند.
در این مثال ، ما تابع ژنراتور را سه بار با مقادیر مختلف متوقف می کنیم و در انتها یک مقدار را برمی گردانیم. سپس آبجکت ژنراتور خود را به متغیر ژنراتور اختصاص می دهیم.
// Create a generator function with multiple yields
function* generatorFunction() {
yield ‘Neo’
yield ‘Morpheus’
yield ‘Trinity’

return ‘The Oracle’
}

const generator = generatorFunction()

حال ، هنگامی که ما تابع next() را بر روی تابع ژنراتور فراخوانی می کنیم ، هر بار که با تابع yield مواجه می شود متوقف خواهد شد. done بعد از هر بار yield روی false تنظیم خواهد شد و این نشان می دهد که ژنراتور تمام نشده است. هنگام رویارویی با return ، یا وقتی yield دیگری در تابع نباشد ، done  روی true تنظیم میشود ​​و ژنراتور به پایان می رسد.
از روش next() چهار بار در یک ردیف استفاده کنید
// Call next four times
generator.next()
generator.next()
generator.next()
generator.next()
چهار خط زیر را به ترتیب نشان می دهد:
Output
{value: “Neo”, done: false}
{value: “Morpheus”, done: false}
{value: “Trinity”, done: false}
{value: “The Oracle”, done: true}

توجه داشته باشید که ژنراتور نیازی به return ندارد. در صورت حذف ، آخرین تکرار این عبارت را باز میگرداند: {value: undefined, done: true} ، چرا که هر فراخوانی بعدی به next() پس از اتمام ژنراتور به پایان می رسد.
تکرار در یک ژنراتور
با استفاده از روش next() ، ما به طور دستی از طریق آبجکت ژنراتور تمام ویژگی های value  و done  تمام آبجکت را تکرار می کنیم. با این حال ، درست مانند Array ، Map ، و Set ، یک ژنراتور از پروتکل تکرار پیروی می کند و می تواند با استفاده از for…of تکرار شود:
// Iterate over Generator object
for (const value of generator) {
console.log(value)
}

خروجی زیر باز می گردد:
Output
Neo
Morpheus
Trinity

همچنین می توان از اپراتور spread برای تعیین مقادیر یک ژنراتور به یک آرایه استفاده کرد.
// Create an array from the values of a Generator object
const values = […generator]

console.log(values)

آرایه زیر را ارائه می دهد:
Output
(3) [“Neo”, “Morpheus”, “Trinity”]

هم spread و هم for..of ، return را در مقادیر فاکتور نمیگیرند (در این حالت، ‘The Oracle’ خواهد بود)
توجه: در حالی که هر دو روش برای کار با ژنراتورهای محدود مؤثر هستند ، اگر یک ژنراتور با یک جریان داده نامتناهی سر و کار داشته باشد ، بدون ایجاد یک حلقه نامحدود امکان استفاده مستقیم از spread یا for… of وجود ندارد.

بستن یک ژنراتور
همانطور که مشاهده کردیم ، یک ژنراتور می تواند ویژگی های done  خود را روی true تنظیم کرده و وضعیت خود را با تکرار در تمام مقادیر خود روی closed تنظیم کند. دو روش دیگر وجود دارد که فوراً یک ژنراتور را کنسل کنید: با روش return () و با روش throw().
با return () ، ژنراتور می تواند در هر نقطه خاتمه یابد ، دقیقاً مثل اینکه عبارت return () در بدنه تابع بوده باشد. می توانید یک آرگومان را به return () بفرستید، یا آن را به صورت یک مقدار نامشخص خالی بگذارید.
برای نشان دادن return () ، ما یک ژنراتور با چند مقدار yield ایجاد می کنیم اما در تعریف تابع return وجود ندارد.
function* generatorFunction() {
yield ‘Neo’
yield ‘Morpheus’
yield ‘Trinity’
}

const generator = generatorFunction()

اولین next () به ما “Neo” می دهد ، که done روی false تنظیم شده است. اگر بلافاصله پس از آن از روش return () در ژنراتور استفاده كنیم ، اکنون مقدار عبور داده شده را دریافت می كنیم و done روی true تنظیم می شود. هرگونه فراخوانی دیگر به next () پاسخ ژنراتور کامل شده با مقدار نامشخص را می دهد.
برای نشان دادن این ، سه روش زیر را روی ژنراتور اجرا کنید:
generator.next()
generator.return(‘There is no spoon!’)
generator.next()

این سه نتیجه را می دهد:
Output
{value: “Neo”, done: false}
{value: “There is no spoon!”, done: true}
{value: undefined, done: true}

روش return () آبجکت Generator را مجبور به تکمیل و چشم پوشی از کلمات کلیدی دیگر yield می کند. این امر به ویژه در برنامه نویسی ناهمزمان مفید خواهد بود، هنگامی که شما نیاز به لغو توابع دارید ، از جمله قطع یک درخواست وب در هنگامی که کاربری می خواهد یک عمل متفاوت انجام دهد ، زیرا نمی توان مستقیماً یک promise را لغو کرد.
اگر بدنه یک تابع ژنراتور راهی برای گرفتن و مقابله با خطاها داشته باشد ، می توانید از روش throw() برای انتقال خطا به ژنراتور استفاده کنید. این کار ژنراتور را به کار می اندازد، خطا را وارد می کند و ژنراتور را خاتمه می دهد.
برای نشان دادن این امر ، try…catch را وارد بدنه تابع ژنراتور میکنیم و در صورت یافتن خطا آن را log میکند:
// Define a generator function with a try…catch
function* generatorFunction() {
try {
yield ‘Neo’
yield ‘Morpheus’
} catch (error) {
console.log(error)
}
}

// Invoke the generator and throw an error
const generator = generatorFunction()

اکنون ، متد next () را اجرا خواهیم کرد و به دنبال آن () throw:
generator.next()
generator.throw(new Error(‘Agent Smith!’))

خروجی زیر را می دهد:
Output
{value: “Neo”, done: false}
Error: Agent Smith!
{value: undefined, done: true}

با استفاده از () throw ، خطایی به ژنراتور تزریق کردیم که با try…catch پیدا شد و وارد کنسول گردید.
روشها و حالتهای آبجکت ژنراتور
در جدول زیر لیستی از روش های قابل استفاده در ابجکت های ژنراتور نشان داده شده است:
روش توصیف
next() مقدار بعدی ژنراتور را برمیگرداند
return() مقداری را در ژنراتور برمیگرداند و ژنراتور را به پایان میرساند
throw() خطای ایجاد میکند و ژنراتور را به پایان میرساند
next ()
در جدول بعدی حالت های احتمالی یک آبجکت ژنراتور آورده شده است:
وضعیت توضیحات
suspended ژنراتور اجر را متوقف کرده اما به اتمام نرسیده است
closed ژنراتور به وسیله برخورد با خطای ، بازگشت یا تکرار تمام مقادیر ، خاتمه یافته است

نمایندگی yield
علاوه بر اپراتور yield معمولی ، ژنراتورها می توانند از عبارت yield* نیز استفاده کنند تا مقادیر بیشتری را به ژنراتور دیگر واگذار کنند. هنگامی که با yield* در یک ژنراتور مواجهه انجام می شود ، وارد ژنراتور تفویض شده می شود و با تمام yieldها تا زمانی که آن ژنراتور بسته شود ، تکرار را آغاز می کند. این ویژگی می تواند برای جدا کردن توابع مختلف ژنراتور برای سازماندهی معنایی کد شما مورد استفاده قرار گیرد ، در حالی که هنوز همه yieldهای آنها به ترتیب درست قابل تکرار هستند.
برای توضیف بیشتر ، می توانیم دو تابع ژنراتور ایجاد کنیم که یکی از آنها yield* را در دیگری اجرا می کند:
// Generator function that will be delegated to
function* delegate() {
yield 3
yield 4
}

// Outer generator function
function* begin() {
yield 1
yield 2
yield* delegate()
}

در مرحله بعدی ، بیایید از طریق تابع ژنراتور begin() تکرار انجام دهیم:
// Iterate through the outer generator
const generator = begin()

for (const value of generator) {
console.log(value)
}

مقدار زیر را به ترتیب تولید ارائه می دهد:
Output
1
2
3
4

ژنراتور خارجی مقادیر 1 و 2 را میدهد ، سپس با yield* به ژنراتور دیگر واگذار میکند و 3 و 4 را برمیگرداند.
yield* همچنین می تواند به هر آبجکتی که قابل تکرار باشد ، مانند یک آرایه یا یک نقشه واگذار شود. واگذاری yield می تواند در سازماندهی کد کمک کننده باشد ، زیرا هر تابعی در یک ژنراتور که بخواهد از yield استفاده کند نیز باید یک ژنراتور باشد.
جریان های بی نهایت داده
یکی از جنبه های مفید ژنراتورها ، امکان کار با جریان ها و مجموعه های اطلاعات نامحدود است. این را می توان با ایجاد یک حلقه نامحدود در داخل یک تابع ژنراتور نشان داد که یک عدد را یک به یک افزایش می دهد.
در بلوک کد زیر این تابع ژنراتور را تعریف می کنیم و سپس ژنراتور را شروع می کنیم:
// Define a generator function that increments by one
function* incrementer() {
let i = 0

while (true) {
yield i++
}
}

// Initiate the generator
const counter = incrementer()

اکنون با استفاده از next () مقادیر را تکرار کنید:
// Iterate through the values
counter.next()
counter.next()
counter.next()
counter.next()

خروجی زیر را می دهد
Output
{value: 0, done: false}
{value: 1, done: false}
{value: 2, done: false}
{value: 3, done: false}

این تابع مقادیر پی در پی را در حلقه نامحدود برمیگرداند ، در حالی که ویژگی done روی false میماند ، و اطمینان حاصل می کند که تمام نمی شود.
در کار با ژنراتورها ، لازم نیست نگران ایجاد یک حلقه نامحدود باشید ، زیرا می توانید به خواست خود متوقف کنید و از سر بگیرید. با این حال ، شما هنوز هم باید در مورد چگونگی استناد به ژنراتور احتیاط کنید. اگر در یک جریان داده نامتناهی از spread یا for …of استفاده می کنید ، همچنان یک حلقه بی نهایت را یکباره تکرار می کنید ، که باعث کرش محیط می شود.
برای یک مثال پیچیده تر از یک جریان داده نامتناهی ، می توانیم یک تابع ژنراتور فیبوناچی ایجاد کنیم. دنباله فیبوناچی ، که به طور مداوم دو مقدار قبلی را با هم جمع می کند ، می تواند با استفاده از یک حلقه نامحدود در یک ژنراتور به شرح زیر نوشته شود:
// Create a fibonacci generator function
function* fibonacci() {
let prev = 0
let next = 1

yield prev
yield next

// Add previous and next values and yield them forever
while (true) {
const newVal = next + prev

yield newVal

prev = next
next = newVal
}
}

برای آزمایش این مورد ، می توانیم از یک تعداد محدود حلقه کمک بگیریم و دنباله فیبوناچی را بر روی کنسول چاپ کنیم.
// Print the first 10 values of fibonacci
const fib = fibonacci()

for (let i = 0; i < 10; i++) {
console.log(fib.next().value)
}

خروجی زیر را نشان می دهد:
Output
0
1
1
2
3
5
8
13
21
34

توانایی کار با مجموعه داده های نامتناهی بخشی از ویژگی هایی است که ژنراتورها را بسیار قدرتمند می کند. این می تواند برای مثالهایی مانند اجرای اسکرول نامحدود در یک برنامه وب مفید باشد.
انتقال مقادیر در ژنراتورها
در طول این مقاله ، ما از ژنراتورها به عنوان تکرارگر استفاده کرده ایم و در هر تکرار مقادیری به دست آورده ایم. علاوه بر تولید مقادیر ، ژنراتورها می توانند مقادیری را نیز از next () مصرف کنند . در این حالت ، yield شامل یک مقدار است.
توجه به این نکته ضروری است که اولین next () که فراخوانی می شود مقداری را منتقل نمی کند ، بلکه فقط ژنراتور را راه اندازی می کند. برای نشان دادن این ویژگی ، می توانیم مقدار yield را ثبت کنیم و next () را با برخی از مقادیر چند بار فراخوانی کنیم.
function* generatorFunction() {
console.log(yield)
console.log(yield)

return ‘The end’
}

const generator = generatorFunction()

generator.next()
generator.next(100)
generator.next(200)

خروجی زیر را به دست می دهد:
Output
100
200
{value: “The end”, done: true}

همچنین می توان ژنراتور را با مقدار اولیه بذردهی کرد. در مثال زیر ، حلقه ای را ایجاد می کنیم و هر مقدار را به روش next () منتقل می کنیم ، اما یک آرگومان را نیز به تابع اولیه منتقل می کنیم:
function* generatorFunction(value) {
while (true) {
value = yield value * 10
}
}

// Initiate a generator and seed it with an initial value
const generator = generatorFunction(0)

for (let i = 0; i < 5; i++) {
console.log(generator.next(i).value)
}

ما مقدار را از next () بازیابی می کنیم و مقدار جدیدی را در تکرار بعدی میگیریم که ضرب مقدار قبلی در ده است . خروجی زیر را نشان می دهد:
Output
0
10
20
30
40

راه دیگر برای کار با یک ژنراتور این است که ژنراتور را در تابعی محصور کنید که همیشه قبل از انجام هر کار دیگری ، next () را فراخوانی میکند.
async/await به همراه ژنراتورها
یک تابع ناهمزمان نوعی از توابع موجود در ES6 + JavaScript است که با ایجاد ظاهر همزمان، کار با داده های ناهمزمان را آسان تر می کند. ژنراتورها دارای قابلیتهای گسترده تری نسبت به توابع ناهمزمان هستند ، اما قادر به تکرار رفتارهای مشابه هستند. اجرای برنامه نویسی ناهمزمان از این طریق می تواند انعطاف پذیری کد شما را افزایش دهد.
در این بخش نمونه ای از بازتولید async/await را با ژنراتورها نشان خواهیم داد.
بیایید یک تابع ناهمزمان ایجاد کنیم که از API Fetch برای دریافت داده از API JSONPlaceholder استفاده میکند (که داده های JSON مثال را برای اهداف آزمایش ارائه می دهد) و پاسخ را به کنسول وارد می کند.
با تعریف تابعی ناهمزمان به نام getUsers که داده ها را از API دریافت می کند و مجموعه ای از ابجکت ها را برمی گرداند ، شروع کرده سپس getUsers را فراخوانی کنید:
const getUsers = async function() {
const response = await fetch(‘https://jsonplaceholder.typicode.com/users’)
const json = await response.json()

return json
}

// Call the getUsers function and log the response
getUsers().then(response => console.log(response))

با این کار داده های JSON مشابه زیر ارائه می شود:
Output
[ {id: 1, name: “Leanne Graham” …},
{id: 2, name: “Ervin Howell” …},
{id: 3, name”: “Clementine Bauch” …},
{id: 4, name: “Patricia Lebsack”…},
{id: 5, name: “Chelsey Dietrich”…},
…]

با استفاده از ژنراتورها ، می توانیم چیزی تقریباً یکسان ایجاد کنیم که از کلمات کلیدی async/await استفاده نکند. در عوض ، از تابع جدیدی که ایجاد می کنیم استفاده می کند و به جای promiseهای await ، مقادیر را yield میکند.
در بلوک کد زیر ، تابعی به نام getUsers را تعریف می کنیم که از تابع جدید asyncAlt (که بعداً خواهیم نوشت) استفاده می کند تا async / await را شبیه سازی کند.
const getUsers = asyncAlt(function*() {
const response = yield fetch(‘https://jsonplaceholder.typicode.com/users’)
const json = yield response.json()

return json
})

// Invoking the function
getUsers().then(response => console.log(response))

همانطور که می بینیم ، تقریباً شبیه اجرای async/await است ، با این تفاوت که یک تابع ژنراتور وجود دارد که مقادیر را yield میکند.
اکنون می توانیم یک تابع asyncAlt ایجاد کنیم که شبیه به یک تابع ناهمزمان باشد. asyncAlt یک تابع ژنراتور به عنوان یک پارامتر دارد ، که تابع ما میباشد و promiseهایی را که باز می گرداند yield میکند. asyncAlt خود یک تابع را برمی گرداند و هر promise ای که می یابد را تا آخرین مورد برطرف می کند:
// Define a function named asyncAlt that takes a generator function as an argument
function asyncAlt(generatorFunction) {
// Return a function
return function() {
// Create and assign the generator object
const generator = generatorFunction()

// Define a function that accepts the next iteration of the generator
function resolve(next) {
// If the generator is closed and there are no more values to yield,
// resolve the last value
if (next.done) {
return Promise.resolve(next.value)
}

// If there are still values to yield, they are promises and
// must be resolved.
return Promise.resolve(next.value).then(response => {
return resolve(generator.next(response))
})
}

// Begin resolving promises
return resolve(generator.next())
}
}

همان خروجی نسخه async / await را خواهد داد:
Output
[ {id: 1, name: “Leanne Graham” …},
{id: 2, name: “Ervin Howell” …},
{id: 3, name”: “Clementine Bauch” …},
{id: 4, name: “Patricia Lebsack”…},
{id: 5, name: “Chelsey Dietrich”…},
…]

توجه داشته باشید که این اجرا برای نشان دادن چگونگی استفاده از ژنراتورها به جای async / await است و یک طراحی آماده برای تولید نیست. این روش در تنظیمات خطایی ندارد و همچنین توانایی انتقال پارامترها به مقادیر yield را ندارد. گرچه این روش می تواند انعطاف پذیری را به کد شما بیفزاید ، اما اغلب async/awaitانتخاب بهتری خواهد بود ، زیرا جزئیات اجرا را خلاصه می کند و به شما امکان می دهد تا روی نوشتن کد موثر تمرکز کنید.
نتیجه
ژنراتورها فرآیندهایی هستند که می توانند اجرا را متوقف کرده و از سر گرفته شوند. آنها یکی از ویژگی های قدرتمند و همه کاره جاوا اسکریپت هستند ، اگرچه معمولاً مورد استفاده قرار نمی گیرند. در این آموزش با توابع ژنراتور و آبجکت های ژنراتور ، روش های موجود برای ژنراتورها ، عملگرهای yield* و yield و ژنراتورهای مورد استفاده با مجموعه داده های محدود و نامتناهی آشنا شدیم. همچنین یک راه برای پیاده سازی کد ناهمزمان را بدون کال بک های آشیانه ای یا زنجیره های طولانی promise بررسی کردیم.
اگر می خواهید در مورد دستورات JavaScript بیشتر بیاموزید ، به آموزش درک، اتصال ، فراخوانی و اعمال در JavaScript و فهم Map و تنظیم آبجکت ها در آموزش های JavaScript مراجعه کنید.

 

از این لینک ها زیر می توانید آمورش های بیشتری برای لینوکس پیدا کنید :

نحوه نصب Nginx در CentOS 8  –  استفاده از Cron برای خودکارسازی کارها در اوبونتو 18

پکیج کردن و انتشار برنامه Snap در اوبونتو 18نصب و استفاده ازRadamsa برای فوز کردن برنامه ها روی Ubuntu 18

استقرارهای تولید Node.js خود را با Shipit در CentOS 7 –  نحوه راه اندازی Eclipse Theia Cloud IDE Platform در Debian 10

چگونگی استفاده از migrations و seeders دیتابیس  –  نحوه نصب Docker Compose در Debian 10

نحوه نصب R روی اوبونتو 18.04 – چگونه می توان با کتابخانه (library) درخواست ها در پایتون شروع به کار کرد

چگونه می توان هاست های مجازی Apache را در اوبونتو 18.04  –  نحوه اجرای صفحه گذاری در MySQL با PHP روی اوبونتو 18.04

نصب پشته Nginx، MySQL، PHP LEMP در CentOS 8 – نحوه تنظیم پلتفرم Eclipse Theia Cloud IDE در CentOS 7

نحوه نصب پشته یا استک Nginx ، MySQL ، PHP LEMP  –  بسته بندی برنامه Laravel 6 برای توسعه با Docker Compose

مراحل ایمن سازی Apache HTTP در FreeBSD 12  – بهینه سازی درخواست های MySQL با ذخیره سازی ProxySQL در اوبونتو 16

درک Objectهای Map و Set در JavaScript  –  استفاده از Ansible برای نصب و راه اندازی وردپرس با LAMP در اوبونتو 18

نحوه راه اندازی Eclipse Theia Cloud IDE در اوبونتو  –  چگونه می توان پلتفرم كد سرور Cloud IDE را در اوبونتو 18.04

نحوه استفاده از Cron برای خودکارسازی کارها در CentOS 8   –  چگونه می توان از رول های ansible برای انتزاع محیط زیرساختی

نحوه نوشتن کد ناهمگام (غیر همزمان) در Node.js –  نحوه پیکربندی یک خوشه Galera با MySQL در سرورهای اوبونتو 18

راه اندازی اولیه سرور با CentOS 8 –   تهیه نسخه پشتیبان و بازیابی یک خوشه Kubernetes

نحوه تنظیم کلیدهای SSH در CentOS 8 –  نحوه نصب و استفاده از PostgreSQL در CentOS 7

نحوه ساختن یک برنامه Node.js با Docker  Quickstart  –  چگونه می توان پلتفرم Eclipse Theia Cloud IDE را روی اوبونتو

چگونه می توان هاست های مجازی Apache را در اوبونتو  –  مدیریت DNS با استفاده از DNSControl در Debian 10

نحوه تایید صحت رمز عبور با Apache در اوبونتو 18.04 –  چگونه می توان پلتفرم Cloud IDE کد سرور را روی CentOS 7

نحوه نصب و استفاده از TimescaleDB در CentOS 7نحوه نصب Apache Kafka در Debian 10

نحوه تایید صحت رمز عبور با Apache در اوبونتو 18.04  –  نحوه نصب وردپرس با OpenLiteSpeed ​​در اوبونتو 18.04

 

 

کلمات کلیدی خرید سرور

خرید vps – خرید سرور مجازی – خرید سرور – سرور هلند – فروش vps – سرور مجازی آمریکا – خریدvps – سرور مجازی هلند – فروش سرور مجازی – سرور آمریکا – vps – سرور مجازی انگلیس – سرور مجازی آلمان – سرور مجازی کانادا – خرید vps آمریکا – خرید وی پی اس – سرور – خرید سرور مجازی هلند – vps خرید – سرور مجازی فرانسه – سرور مجازی هلند – خرید vps آمریکاخرید سرور مجازی ارزان هلندvpsخرید vps هلندخرید سرور مجازی آمریکاخرید vps فرانسهتست vpsسرور مجازی تستسرور مجازی ویندوزارزانترین vpsخرید وی پی اسvps ارزان – 


https://vpsgol.net/product/vps-germany/

https://vpsgol.net/product/vps-usa/

https://vpsgol.net/product/vps-france/

https://vpsgol.net/product/vps-canada/

https://vpsgol.net/product/vps-poland/

https://vpsgol.net/product/vps-netherlands/

https://vpsgol.net/product/vps-england/