آموزش Generator در ES6

24 مرداد 1397
20-Resources-on-ES6-for-JavaScript-Developers

در این آموزش قصد داریم آموزش کار با Generator ها در ES6 را بررسی کنیم.

مباحثی که در این مقاله به آن می پردازیم عبارتند از:

1-Generatorها

2- توابع Generator

3- yield

Generator ها

Generator ها چرخه های اجرای برنامه را کنترل می کنند. با کمک آنها می توانید هر زمان که خواستید در اجرای برنامه تان یک وقفه ایجاد کنید، که یکی از ویژگی های قدرتمند اکما اسکریپت 6 (ES6) است. به Generator ها توابع قابل توقف هم می گویند. چون با کمک تابع Generator می توانید برنامه تان را هرچند بار که خواستید متوقف و restart کنید.

توابع استاندارد

این تابع یک پارامتر اختیاری می گیرد و یک مقدار جدید را بر می گرداند. توابع یکی از ویژگی های اساسی هر زبان برنامه نویسی است. هنگامی که تابع را فراخوانی می کنیم، اجرای آن شروع شده و ما نمی توانیم تا زمانی که اجرای آن کامل نشده باشد، در اجرای آن وقفه ایجاد کنیم. پس ما نمی توانیم در طول اجرای برنامه آن را متوقف کنیم.

//main.js

let fun = hello => console.log(`${hello}, how are you`);
fun('hello');

خروجی

hello, how are you

در صورتی که کد بالا را بطور مستقیم در مرورگر اجرا کنید ممکن است با خطاهای زیر مواجه شوید:

خطاهای احتمالی

1- ممکن است خطای سینتکسی دریافت کنید

2- در صورتی که کد بالا را به طور مستقیم در مرورگر اجرا کنید به احتمال زیاد webpack نمی تواند کد شما را کامپایل کند و این باعث بروز خطا در برنامه می شود.

راه حل این مسئله

ابتدا مقاله آموزش نصب و راه اندازی محیط توسعه اکما اسکریپت 6 را مطالعه کنید و سپس کدهای بالا را در فایل main.js قرار دهید.

توابع Generator

سینتکس

function *hello(){
   // body
}

یا

function* hello() {
  //body
}

مثال 1

//main.js

function* generate() {
   console.log(`hello`);
}
let gen = generate();
console.log(gen);

ابتدا مرورگرتان را باز کنید سپس دکمه های ترکیبی ctrl+shift-I را فشار دهید تا وارد محیط developer tools مرروگر شوید، سپس وارد پنل console شده، و همان طور که می بینید هیچ چیزی را در آنجا مشاهده نمی کنید. پس دستور console.log برنامه چرا اجرا نشده است؟ نگران نباشید. این اتفاق در واقع وظیفه ی Generator را نشان می دهد. Generator ها مانند توابع معمولی کار می کنند.

Generator ها یک Iterator بر می گرداند، و شما می توانید متد next() را روی آن اجرا کنید.

در صورتی که نمی دانید Iterator چیست، لطفا مقاله آموزش Iterator در اکما اسکریپت ۶ را مطالعه بفرمایید.

//main.js

function* generate() {
   console.log(`hello`);
}
let gen = generate();
console.log(gen.next());

خب پس دیدیم که تابع Generator()  یک آبجکت از نوع Iterator بر می گرداند که باید تابع next() را روی آن فراخوانی کنیم.

در صورتی که با Iterator آشنایی داشته باشید، می دانید که یک آبجکت شامل دو پروپرتی را به ما بر می گرداند

Object {value: undefined, done: true}

تا اینجا فهمیدید که Generator ها یک آبجکت Iterable تولید می کنند که می توانید متدهای Iterator، مثل next() را روی آن فراخوانی کنید.

در زیر یک مثال آوردیم که خروجی آن دقیقا مانند کد بالا است:

خروجی

Object {value: undefined, done: true}

مقدار پروپرتی value برابر undefined است. ما می توانیم به روش های مختلف به این آبجکت مقدار نسبت بدهیم.

//main.js

function* generate() {
    yield 'krunal'
   console.log(`hello`);
}
let gen = generate();
console.log(gen.next().value);

خروجی

krunal

Yield

در generatorها ارتباطات به صورت دو طرفه اتفاق می افتند.

شما می توانید مقادیر را داخل تابع Generator پاس بدهید، سپس با استفاده از تابع next() مقادیر نسبت داده شده را دریافت کنید.

در مثال بالا، ما از کلمه کلیدی yield استفاده کردیم، که به وسیله آن می توانیم مقادیر را به توابع Generator نسبت بدهیم. در مثال بالا، رشته Krunal را به تابع Generator نسبت دادیم. سپس gen.next() در خروجی یک آبجکت شامل دو پروپرتی مانند {value:’Krunal’ , done:false} بود. همچنین می توانیم مقادیر مورد نظرمان را به عنوان آرگومان به متد Generator پاس بدهیم:

//main.js

function* generate() {
   let result = yield;
   console.log(result);
}
let gen = generate();
gen.next();
gen.next('krunal');

خروجی

krunal

مثال 2

/main.js

function* generate() {
  yield 1;
  yield ['krunal','ankit','rushabh'];
}
let gen = generate();
console.log(gen.next().value);
console.log(gen.next().value);

خروجی

1
['krunal','ankit','rushabh']

در مثال بالا ما دو مقدار را به آن نسبت دادیم و مقادیر را یکی پس از دیگری چاپ می کنیم. حال اگر بخواهیم در میان عناصر آرایه حرکت کنیم، می توانیم کد زیر را بنویسیم:

//main.js

function* generate() {
  yield 10;
  yield* ['krunal','ankit','rushabh'];
}
let gen = generate();
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);

خروجی

10
krunal
ankit
rushabh

دستور yield* همانند iteratorها رفتار می‌کند، که می توانیم مقادیر را گرفته و آنها را یکی یکی چاپ کنیم.

مثال 3

//main.js

function* generate() {
  yield 10;
  yield 20;
  yield 30;
}
let gen = generate();
for(value of gen){
    console.log(value);
}

این مثال اثباتی برای این موضوع است که generatorها یک آبجکت iterator تولید می کنند.

روی آبجکت Iterator می توانیم توسط یک حلقه for…of  در میان عناصر حرکت کرده و آنها را یکی یکی چاپ کنیم.

آموزش Generator در ES6

 نکات مهم

1- Generator ها یک آبجکت از نوع iterable تولید می کنند که می توانیم متد next() را روی آن فراخوانی کنیم.

2-Generator ها توابعی برای توقف و شروع برنامه دارند که می توانید هر بار که خواستید از آنها استفاده کنید.

3- شما می توانید از Generator ها برای لغو برنامه هایی که به صورت غیرهمزمان (asynchronous) اجرا می شوند استفاده کنید.

4- توابع Generator همانند توابع عادی هستند با این تفاوت که یک کاراکتر ستاره (*) بعد از کلمه function استفاده می شود.

5- در صورت فراخوانی یک متد Generator، این متد مانند متدهای عادی اجرا نمی شود بلکه فقط یک آبجکت از نوع iterator بر می گرداند.

6- می توانیم یک آرگومان را به متد next() پاس بدهیم و سپس yield اجرای یک Generator را از سر می گیرد.

7- yield* می تواند به عنوان یک iterator عمل کند و قادر هستیم از یک حلقه for…of برای آن استفاده کنیم.

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.